Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #103961
| Newsgroups | comp.lang.python |
|---|---|
| Date | 2016-03-03 04:52 -0800 |
| References | <84965b86-819b-4924-bca9-e82eed040606@googlegroups.com> <mailman.146.1457007243.20602.python-list@python.org> |
| Message-ID | <de3f3492-063d-469c-8ad2-c93098335a2f@googlegroups.com> (permalink) |
| Subject | Re: yield in try/finally case |
| From | 刘琦帆 <lqf.txx@gmail.com> |
在 2016年3月3日星期四 UTC+8下午8:14:29,Oscar Benjamin写道: > On 3 March 2016 at 11:52, 刘琦帆 <lqf.txx@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.
Back to comp.lang.python | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
yield in try/finally case 刘琦帆 <lqf.txx@gmail.com> - 2016-03-03 03:52 -0800
Re: yield in try/finally case Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2016-03-03 12:13 +0000
Re: yield in try/finally case 刘琦帆 <lqf.txx@gmail.com> - 2016-03-03 04:52 -0800
Re: yield in try/finally case Peter Otten <__peter__@web.de> - 2016-03-03 14:47 +0100
Re: yield in try/finally case Random832 <random832@fastmail.com> - 2016-03-03 10:12 -0500
Re: yield in try/finally case Peter Otten <__peter__@web.de> - 2016-03-03 17:20 +0100
Re: yield in try/finally case Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2016-03-03 16:24 +0000
Re: yield in try/finally case Random832 <random832@fastmail.com> - 2016-03-03 10:00 -0500
Re: yield in try/finally case Steven D'Aprano <steve@pearwood.info> - 2016-03-04 02:57 +1100
csiph-web