Комбинация сопрограмм и сбора ресурсов, похоже, может иметь некоторые непреднамеренные (или неинтуитивные) последствия.
Основной вопрос: работает ли что-то подобное:
def coroutine():
with open(path, 'r') as fh:
for line in fh:
yield line
Что он делает. (Вы можете проверить это!)
Более глубокое беспокойство состоит в том, что with
должно быть чем-то альтернативой finally
, где вы гарантируете, что ресурс будет выпущен в конце блока. Coroutines может приостановить и возобновить выполнение из блока 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?
Update
В предыдущем примере я собирался конкурировать с файлами с блокировкой записи, но поскольку большинство операционных систем выделяют дескрипторы файлов для каждого процесса, там не будет никаких утверждений. (Kudos @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()