'NoneType' in contextmanager prevent proper RuntimeError to be raised
Cameron Simpson
cs at zip.com.au
Wed May 20 19:58:25 EDT 2015
On 20May2015 16:20, Daniel Gonçalves <daniel.base4 at gmail.com> wrote:
>When you decorate a function with contextmanager that didn't yield you got an AttributeError instead of a proper RuntimeError "generator didn't yield". For example:
>
>>>> @contextlib.contextmanager
>>>> def foo():
>... pass
>...
>>>> with foo():
>... do_something()
>...
>Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> File "/usr/lib/python2.7/contextlib.py", line 17, in __enter__
> return self.gen.next()
>AttributeError: 'NoneType' object has no attribute 'next'
>
>The proper exception should be a RuntimerError with the "generator didn't yield" message. At least for Python version 2.7.6.
Unfortunately no.
Your function foo() is _not_ a generator because it does not have a yield
statement. Therefore it is a normal funcion which returns None (because it also
lacks a return statement).
contextlib.contextmanager works by _calling_ the inner foo(). It expected to
get a generator back. But your foo() returns None, _not_ a generator.
hence the error message: contextlib.contextmanager tries to use the return
value with next(), which of course fails with exactly the exception one might
expect.
To get "generator didn't yield" you need to actually have a generator. Eg:
@contextlib.contextmanager
def foo():
if false:
yield
Untested, though.
Cheers,
Cameron Simpson <cs at zip.com.au>
More information about the Python-list
mailing list