On 3 March 2016 at 11:52, 刘琦帆 <lqf....@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 -- https://mail.python.org/mailman/listinfo/python-list