[Python-il] What do you think about my `ContextManager`?
cool-rr at cool-rr.com
Thu Jan 6 17:50:22 IST 2011
On Thu, Jan 6, 2011 at 11:58 AM, Tal Einat <taleinat at gmail.com> wrote:
> On Thu, Jan 6, 2011 at 1:33 AM, cool-RR <cool-rr at cool-rr.com> wrote:
>> Thanks for the critique Tal.
>> I updated the `context_manager` module in response, here is the new
>> (Note that this is a link to my `development` branch, so it will get
>> updated as I continue working on it.)
>> In Thu, Jan 6, 2011 at 12:36 AM, Tal Einat <taleinat at gmail.com> wrote:
>>> How about something like: "A class for writing enhanced context managers.
>>> Allows using context managers as decorators, a new succinct way to define
>>> context managers, and some other goodies."
>> Here's the new description I came up, tell me if you think it's good
>> Defines the `ContextManager` and `ContextManagerType` classes.
>> These classes allow for greater freedom both when (a) defining context
>> and when (b) using them. It allows defining context managers either by (1)
>> using the classic `__enter__` and `__exit__` interface, or (2) using a
>> stand-alone generator function or (3) using a class that defines a
>> `manage_context` generator function. In addition, the `ContextManager`
>> allows using a context manager as a decorator to a function, which for
>> cases is a better alternative than using the `with` keyword.
> I still find this to be too long, in the sense that I have to read the
> entire paragraph just to get a basic idea of what this does. How about
> keeping this, but adding to the first sentence, something like:
> Defines the `ContextManager` and `ContextManagerType` classes. Using
> these to define context managers allows using such context managers as
> decorators (in addition to their normal use) and supports writing context
> managers in a new form (as well as the original forms).
Cool, I replaced mine with this one.
>>> I must say, the actual benefits are really unclear. How is using
>>> @MyContextManager() better than contextlib.ContextDecorator (the latter
>>> being more explicit)?
>> How is `ContextDecorator` more explicit? The place where you write
>> "ContextDecorator" is where you *define* you context manager, not where you
>> *use* it. So when you use your context manager as a decorator using
>> Foord's `ContextDecorator`, there is no reference to `ContextDecorator`, so
>> I don't see how it's more explicit.
> You are correct, I misunderstood the use of ContextDecorator. So the use is
> very similar. If the two classes are identical in this sense, you should
> mention that, if not you must describe the differences.
There's this sentence in the docstring: "This functionality is also
available in the standard library of Python 3.2+ by using
`contextlib.ContextDecorator`, but here it is combined with all the other
goodies given by `ContextManager`."
I think it's good enough: I don't want to start describing `ContextManager`
in terms of Foord's `ContextDecorator`, I'd rather describe it directly.
Also the readers might not be familiar with `ContextDecorator`-- It's a
relatively new addition and I'd bet that the vast majority of Python users
aren't aware of it.
>>> How is using the "manage_context()" method better than just defining a
>>> context manager with a function and contextlib.contextmanager?
>>> - Tal
>> There are two cases that I can think of where it's better. In the version
>> of `context_manager.py` you saw before I gave an example of the first, and
>> in the new version that I linked to above I also explain the second.
>> The first case where this is helpful is when you want a context manager
>> which calls another context manager. For example, this code:
>> class MyContextManager(ContextManager):
>> def manage_context(self):
>> with some_lock:
>> yield self
>> Is much nicer in my opinion than this code, which is its equivalent:
>> class MyContextManager(ContextManager):
>> def __enter__(self):
>> return self
>> def __exit__(self, *exc):
>> return some_lock.__exit__(*exc)
>> As for the second case, I'll quote the new version of the docstring:
>> Another advantage of this approach over `__enter__` and `__exit__` is
>> it's better at handling exceptions, since any exceptions would be raised
>> inside `manage_context` where we could `except` them, which is much more
>> idiomatic than the way `__exit__` handles exceptions, which is by
>> receiving their type and returning whether to swallow them or not.
> The same can be said for defining context manager via generator functions
> and contextlib.contextmanager. How is your context_manager() form of
> definition better or different than that?
It's true, it's the same mechanism as `contextlib.contextmanager`; The
difference is that in `contextlib.contextmanager` you create a bare context
manager which can do nothing beyond being a context manager. But when you
subclass from `ContextManager` and use `manage_context`, you can put
whatever else you want in this class; You can define methods, inherit from
other classes, etc.
For example, if you already have some class `Foobar` in your project and you
want it to behave as a generator-style context manager, inheriting from my
`ContextManager` is the only solution. (Except coding your own, of course.)
> I hope this is written clearly enough; Possibly an example for this case
>> should be included in the docstring. I'm not sure though.
> It is technically clear. However, the reasons someone would want to use it
> instead of the existing forms of writing context managers aren't clear at
> all. You should give actual examples of things that can be done with your
> classes that can't be done otherwise (or would be significantly more
> - Tal
I added an example for the first case now. I tried giving an example for the
second one, but couldn't find an impressive enough example. I have a few
places where it saved me a few dozen characters, but it's not impressive
enough. So I think I'll stay without an example for the second case.
All the changes can be seen in the most updated version here:
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Python-il