[Python-ideas] Automatic context managers

David Mertz mertz at gnosis.cx
Sat Apr 27 00:55:39 CEST 2013


On Apr 26, 2013, at 3:33 PM, Bruce Leban wrote:
> class SafeOpen(object):
>     def __init__(self, resource):
>         self.resource = resource
>     def __getattr__(self, name):
>         def f(*args, **kws):
>             with open(self.resource) as x:
>                 y = getattr(x, name)(*args, **kws)
>             return y
>         return f
> Wouldn't that close the resource before the use function is actually called? As I read it, it opens, calls getattr(x, 'use'), closes x, then calls x.use().

Nope.  The call is inside the context manager.  Whatever is returned is stored in 'y' before the resource is closed, and that value of y is returned by the proxy function f.

It's easy to try:

  In [23]: SafeOpen('test').read(5)
  Out[23]: 'this\n'

  In [24]: SafeOpen('test').readlines()
  Out[24]: ['this\n', 'and\n', 'that\n', 'and\n', 'other\n']

It would be easy to generalize this to be a SafeAnything class rather than only handle 'open()'.  You could just pass in the name of the context manager to the initializer rather than hardcode it as being 'open()'.  Actually, I sort of like a factory for producing SafeAnythings better:

def safe_factory(context_manager):
    class SafeAnything(object):
        def __init__(self, resource, cm=context_manager):
            self.resource = resource
            self.cm = cm
        def __getattr__(self, name):
            def f(*args, **kws):
                with self.cm(self.resource) as x:
                    y = getattr(x, name)(*args, **kws)
                return y
            return f
    return SafeAnything
SafeOpen = safe_factory(open)

--
The dead increasingly dominate and strangle both the living and the 
not-yet born.  Vampiric capital and undead corporate persons abuse 
the lives and control the thoughts of homo faber.  Ideas, once born,
become abortifacients against new conceptions.




More information about the Python-ideas mailing list