从Gevent循环调用中的阻塞源获取数据

2024-07-07 08:42:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我尝试在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也没有帮助,因为我们必须等待()来获得结果。在

在事件循环回调中,是否有任何方法可以从可能阻塞的源获取数据?在


Tags: 数据fromimportselfurlreadcallback事件
1条回答
网友
1楼 · 发布于 2024-07-07 08:42:18

如果去掉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=...)或{}来改变默认行为。在

相关问题 更多 >