我尝试在Gevent中使用Pycurl来执行HTTP上传。为此,我依赖于geventcurl.py模块,它改变了libcurl的MultiAPI以使用Gevent的事件循环。在
问题出在READFUNCTION回调中。这个回调是在HUB上下文中执行的,因此我们不能wait(),但是这个回调必须返回要上载的数据,在我的例子中,这个数据来自阻塞源。在
下面是一段代码片段,用于说明问题:
#!/usr/bin/env python
from gevent import monkey; monkey.patch_all()
import gevent
from gevent.queue import Queue
import pycurl
from geventcurl import Curl
URL = 'http://localhost:8000/'
class QueueReader:
def __init__(self, q):
self.q = q
def read_callback(self, size):
return self.q.get(timeout=10)
dataq = Queue(10)
c = Curl()
c.setopt(pycurl.URL, URL)
c.setopt(pycurl.UPLOAD, 1)
c.setopt(pycurl.READFUNCTION, QueueReader(dataq).read_callback)
# Start transfer
g = gevent.spawn(c.perform)
for i in xrange(10):
dataq.put(str(i))
gevent.sleep(1)
g.join()
c.close()
要运行这个片段,你只需要听一些东西本地主机:8000,nc -l 8000
就可以了。由于read_callback()
是在集线器上下文中执行的,它不会等待,如果队列为空,它将立即引发Empy异常。使用AsyncResult也没有帮助,因为我们必须等待()来获得结果。在
在事件循环回调中,是否有任何方法可以从可能阻塞的源获取数据?在
如果去掉
timeout=10
,它将等待来自阻塞源的数据。(请参见:http://www.gevent.org/gevent.queue.html,默认行为。)如果read_callback()的阻塞将干扰
for i in xrange(10)
循环的操作,则将该循环放入其自己的greenlet via中,例如gevent.spawn()
。在另外请注意,默认情况下,如果队列已满,}来改变默认行为。在
put()
将阻塞。考虑put_nowait()
、put(timeout=...)
或{相关问题 更多 >
编程相关推荐