我正在使用Python实现一个非常小的库,必须非阻塞。
在某些生产代码上,在某些时候,将完成对此库的调用,并且它需要自己完成工作,以最简单的形式,它将是一个需要将某些信息传递给服务的可调用方。 / p>
这种“将信息传递给服务”是一项非密集型任务,可能会将一些数据发送到HTTP服务或类似的东西。它也不需要并发或共享信息,然而它确实需要在某个时刻终止,可能是超时。
之前我使用过threading
模块,它似乎是最合适的选择,但是使用这个库的应用程序是如此之大,以至于我担心会遇到线程限制。
在本地测试中,我能够在大约2500个生成的线程中达到该限制。
很有可能(考虑到应用程序的大小)我可以很容易地达到这个限制。考虑到以高速率放置任务的内存含义,它也让我厌倦了使用队列。
我也看过gevent
,但是我看不到能够产生一些可以做某些工作并且不加入就终止的东西的例子。我在生成的.join()
或一系列greenlet上调用Greenlet
的示例。
我不需要知道正在完成的工作的结果!它只需要触发并尝试与HTTP服务进行通信,如果没有,则会以合理的超时消亡。
我是否误解了gevent
的指南/教程?是否还有其他可能以完全非阻塞的方式生成一个无法达到~2500限制的可调用方式?
这是线程中的一个简单示例,它可以像我期望的那样工作:
from threading import Thread
class Synchronizer(Thread):
def __init__(self, number):
self.number = number
Thread.__init__(self)
def run(self):
# Simulating some work
import time
time.sleep(5)
print self.number
for i in range(4000): # totally doesn't get past 2,500
sync = Synchronizer(i)
sync.setDaemon(True)
sync.start()
print "spawned a thread, number %s" % i
这就是我用gevent尝试过的,它显然会在最后阻塞 看看工人做了什么:
def task(pid):
"""
Some non-deterministic task
"""
gevent.sleep(1)
print('Task', pid, 'done')
for i in range(100):
gevent.spawn(task, i)
编辑:
我的问题源于我对gevent
的不熟悉。虽然Thread
代码确实产生了线程,但它也阻止了脚本在执行某些工作时终止。
gevent
,否则 .join()
在上面的代码中并没有真正做到这一点。我必须要做的就是看gevent
代码与衍生的greenlets做了一些工作,这是为了让它成为一个长期运行的过程。这肯定解决了我的问题,因为需要生成greenlets的代码是在一个长期运行的进程中完成的。
答案 0 :(得分:5)
如果您希望主线程的持续时间超过任何工作人员,则无需在gevent中调用join
。
join
调用的唯一原因是确保主线程的持续时间至少与所有worker一样长(以便程序不会提前终止)。
答案 1 :(得分:0)
为什么不使用连接的管道或类似方法生成子进程,然后,而不是可调用的,只需将数据放在管道上,让子进程完全带外处理。
答案 2 :(得分:0)
如Understanding Asynchronous/Multiprocessing in Python中所述,asyncoro框架支持异步并发进程。您可以运行数十或数十万个并发进程;作为参考,运行100,000个简单进程大约需要200MB。如果你愿意,你可以在系统的其余部分和协同程序中使用asyncoro混合线程(提供的线程和协同程序不共享变量,但使用协程接口函数来发送消息等。)。