gpt4 book ai didi

python - 从 Python 中的 "with" block 中产生是否安全(为什么)?

转载 作者:IT老高 更新时间:2023-10-28 21:32:02 26 4
gpt4 key购买 nike

协同程序和资源获取的结合似乎会产生一些意想不到的(或不直观的)后果。

基本问题是这样的事情是否有效:

def coroutine():
with open(path, 'r') as fh:
for line in fh:
yield line

它的作用。 (你可以测试一下!)

更深层次的担忧是with应该是 finally 的替代品,您可以确保在 block 的末尾释放资源。协程可以在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?

更新

在前面的示例中,我打算进行写锁定文件句柄争用,但由于大多数操作系统为每个进程分配文件句柄,因此不会出现争用。 (感谢@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()

最佳答案

我真的不明白你问的是什么冲突,也不明白这个例子的问题:同一个文件有两个共存的独立句柄很好。

在回答您的问题时我不知道我了解到,生成器上有一个新的 close() 方法:

close() raises a new GeneratorExit exception inside the generator to terminate the iteration. On receiving this exception, the generator’s code must either raise GeneratorExit or StopIteration.

close() is called when a generator is garbage-collected, so this means the generator’s code gets one last chance to run before the generator is destroyed. This last chance means that try...finally statements in generators can now be guaranteed to work; the finally clause will now always get a chance to run. This seems like a minor bit of language trivia, but using generators and try...finally is actually necessary in order to implement the with statement described by PEP 343.

http://docs.python.org/whatsnew/2.5.html#pep-342-new-generator-features

这样可以处理在生成器中使用 with 语句但它在中间产生但从不返回的情况 - 上下文管理器的 __exit__ 方法将被调用当生成器被垃圾回收时。


编辑:

关于文件句柄问题:我有时会忘记存在不类似于 POSIX 的平台。 :)

就锁而言,我认为 Rafał Dowgird 说“你只需要注意,生成器就像任何其他拥有资源的对象一样”是一针见血。我不认为 with 语句在这里真的很重要,因为这个函数也有同样的死锁问题:

def coroutine():
lock.acquire()
yield 'spam'
yield 'eggs'
lock.release()

generator = coroutine()
generator.next()
lock.acquire() # whoops!

关于python - 从 Python 中的 "with" block 中产生是否安全(为什么)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/685046/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com