【发布时间】:2012-11-03 09:20:21
【问题描述】:
我已阅读有关该主题的所有文档,但似乎我无法很好地掌握 Python 协程的整个概念来实现我想做的事情。
我有一个后台任务(它会生成一些随机文件,但这并不重要),它在无限循环中执行此操作(这是一个观察者)。
我想以最有效的方式实现这个后台任务,我认为微线程(又名协程)是实现这一目标的好方法,但我根本无法让它工作(无论是后台任务或程序的其余部分运行,但不能同时运行!)。
谁能给我一个使用协程实现的后台任务的简单示例?还是我错误地认为协程可以用于此目的?
我正在使用 Python 2.7 原生协程。
我精通并发,尤其是 DBMS 和 Ada,因此我对底层原理了解很多,但我不习惯生成器即协程的概念,这对我来说是很新的概念。
/EDIT:这是我的代码示例,我必须再次强调它不起作用:
@coroutine
def someroutine():
with open('test.txt', 'a') as f:
f.write('A')
while True:
pass
yield 0
@coroutine
def spawnCoroutine():
result = yield someroutine()
yield result
routine = spawnCoroutine()
print 'I am working in parallel!'
# Save 'A' in the file test.txt, but does not output 'I am working in parallel!'
注意:@coroutine 是来自 coroutine.py 的装饰器,由 David Beazley 提供
/最终编辑和解决方案回顾
好的,我的问题已经结束,因为它看起来很模棱两可,事实上 我的问题的真正目的是:澄清协同程序在线程和多处理上的使用。
幸运的是,在可怕的制裁发生之前提交了一个很好的答案!
为了强调上述问题的答案:不,Python 的协程(也不是 bluelet/greenlet)不能用于运行独立的、可能无限受 CPU 限制的任务,因为 协程没有并行性。
这是最让我困惑的。确实,parallelism is a subset of concurrency,因此当前 Python 中的协程实现允许并发任务,但不允许并行任务,这相当令人困惑!这种行为要与 Ada 等并发编程语言的 Tasks 概念明确区分开来。
此外,Python 的线程与协程类似,它们通常在等待 I/O 时切换上下文,因此也不是独立 CPU 密集型任务的理想候选者(请参阅 David Beazley 的 Understanding the GIL )。
我目前使用的解决方案是使用multiprocessing 模块生成子进程。产生后台进程很繁重,但总比什么都不运行要好。这还具有允许分布式计算的优势。
作为替代方案,在 Google App Engine 上,deferred module 和 background_thread module 可以提供有趣的多处理替代方案(例如,通过使用一些实现 Google App Engine API 的库,例如 typhoonae ,虽然我不确定他们是否已经实现了这些模块)。
【问题讨论】:
-
你的代码在哪里? (应该在这里)。
-
您是在 Python 2.x 生成器、3.x 生成器、无堆栈(或 PyPy)本机协程或其他不同的基础上做协程吗?如果是 2.x,您是否通过 dabeaz.com/coroutines/index.html 工作过?有大量的代码示例,当然整个过程都是为了让您掌握概念。
-
@JohnGainesJr。该术语至少在
python-*邮件列表中很常见,它指的是使用res = yield foo(现在是res = yield from foo)结构进行通信的“生成器”。该术语也可以追溯到引入这些功能的原始 PEP。 -
@user1121352 并发与并行并不完全相同,这似乎是您所要求的。基于
yield/next()/send()的协程本身并不是并行的,除非您将它们与线程或greenlets 混合使用。 -
对于这个特定的任务,你可能不应该使用协程,而应该使用真正的线程。
标签: python multithreading generator coroutine