yield in try/finally case

刘琦帆 lqf.txx at gmail.com
Thu Mar 3 07:52:18 EST 2016


在 2016年3月3日星期四 UTC+8下午8:14:29,Oscar Benjamin写道:
> On 3 March 2016 at 11:52, 刘琦帆 <lqf.txx at gmail.com> wrote:
> >
> > "A yield statement is not allowed in the try clause of a try/finally construct.  The difficulty is that there's no guarantee the generator will ever be resumed, hence no guarantee that the finally block will ever get executed; that's too much a violation of finally's purpose to bear." from https://www.python.org/dev/peps/pep-0255/
> >
> > But, meanwhile, the code showed on that page use yield in a try/finally case.
> > It really puzzles me. Is there anything wrong?
> 
> I think what it means is that you can put a yield in the finally block
> but not the try block so:
> 
> # Not allowed
> def  f():
>     try:
>         yield 1
>     finally:
>         pass
> 
> # Allowed
> def f():
>     try:
>         pass
>     finally:
>         yield 1
> 
> However that information is out of date. The restriction was removed
> in some later Python version. Actually the construct is quite common
> when using generator functions to implement context managers:
> 
> @contextlib.contextmanager
> def replace_stdin(newstdin):
>     oldstdin = sys.stdin
>     try:
>         sys.stdin = newstdin
>         yield
>     finally:
>         sys.stdin = oldstdin
> 
> Although the restriction was removed the problem itself still remains.
> There's no guarantee that a finally block will execute if there is a
> yield in the try block. The same happens if you use a context manager
> around a yield statement: the __exit__ method is not guaranteed to be
> called. One implication of this is that in the following code it is
> not guaranteed that the file will be closed:
> 
> def upperfile(filename):
>     with open(filename) as fin:
>         for line in fin:
>             yield line.upper()
> 
> --
> Oscar


It really nice of you to answer the question. But I am still confused with your last example, is there any case that the file with not be closed? I just run the code and no exception occur.



More information about the Python-list mailing list