Welcome, guest | Sign In | My Account | Store | Cart

Since try-finally can't be used in a generator, it can be somewhat tricky to ensure that a resource is released if the generator is exited early. This solution wraps the generator with an enclosing class to ensure the resource is released.

Python, 60 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
Python 2.2.1 (#34, Apr  9 2002, 19:34:33) [MSC 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from __future__ import generators
>>> def g():
...     for i in range(5):
...             yield i
...
>>> for x in g():
...     print x
...
0
1
2
3
4
>>> def acquireResource():
...     print 'Resource Acquired'
...
>>> def releaseResource():
...     print 'Resource Released'
...
>>> class GeneratorWrapper:
...     def __init__(self, generator):
...             self.generator = generator
...             acquireResource()
...     def __del__(self):
...             releaseResource()
...     def __iter__(self):
...             return self
...     def next(self):
...             return self.generator.next()
...
>>> def testNormalUse():
...     w = GeneratorWrapper(g())
...     for x in w:
...             print x
...
>>> testNormalUse()
Resource Acquired
0
1
2
3
4
Resource Released
>>> def testAbortedUse():
...     w = GeneratorWrapper(g())
...     for x in w:
...             print x
...             if x > 2:
...                     return
...
>>> testAbortedUse()
Resource Acquired
0
1
2
3
Resource Released
>>>

Solution due to GvR; I wrote it up here as an example. But don't let that disuade you from correcting my errors!

Created by Michael Chermside on Fri, 31 May 2002 (PSF)
Python recipes (4591)
Michael Chermside's recipes (3)

Required Modules

  • (none specified)

Other Information and Tasks