コルーチンとリソース獲得の組み合わせは、意図しない(または直感的でない)結果をもたらす可能性があるようです。
基本的な質問は、このようなものが機能するかどうかです。
def coroutine():
with open(path, 'r') as fh:
for line in fh:
yield line
それは何をしますか。(あなたはそれをテストすることができます!)
より深い懸念は、ブロックの最後でリソースが解放されることを保証する、with
の代替となるはずであるということです。finally
コルーチンはブロック内から実行を一時停止および再開できますが、競合はどのように解決されますか?with
たとえば、コルーチンがまだ返されていないときに、コルーチンの内側と外側の両方で読み取り/書き込みを使用してファイルを開くと、次のようになります。
def coroutine():
with open('test.txt', 'rw+') as fh:
for line in fh:
yield line
a = coroutine()
assert a.next() # Open the filehandle inside the coroutine first.
with open('test.txt', 'rw+') as fh: # Then open it outside.
for line in fh:
print 'Outside coroutine: %r' % repr(line)
assert a.next() # Can we still use it?
アップデート
前の例では書き込みロックされたファイルハンドルの競合を考えていましたが、ほとんどのOSはプロセスごとにファイルハンドルを割り当てるため、競合は発生しません。(例を指摘してくれた@Milesへの称賛はあまり意味がありませんでした。)これが私の修正された例で、実際のデッドロック状態を示しています。
import threading
lock = threading.Lock()
def coroutine():
with lock:
yield 'spam'
yield 'eggs'
generator = coroutine()
assert generator.next()
with lock: # Deadlock!
print 'Outside the coroutine got the lock'
assert generator.next()