Python上的非阻塞生成器

时间:2013-11-01 22:32:06

标签: python generator yield

我在QT-Application中使用来自请求模块的生成器函数,与请求流示例中的几乎相同:

import json
import requests

def get_stream():
    r = requests.get('http://httpbin.org/stream/20', stream=True)
    for line in r.iter_lines():
        if line:
            yield json.loads(line)

def consume_stream():
    for message in get_stream():
       #do something

但是,当没有传入响应时(例如来自Twitters Streaming API的不定期传入的推文),生成器get_stream将阻止consume_stream方法。

这可能发生在任何情况下,即生成器不立即生成,但是要等待传入消息等,从而阻止消费者。

在Python中是否有任何模式可以以非阻塞方式使用生成器,即如果生成器生成,处理结果,否则在发生下一个结果之前执行其他操作?

4 个答案:

答案 0 :(得分:2)

看看producer-consumer pattern。它通常使用Queue在python中实现。

生成器通常在线程或其他进程中运行(Queue支持),只需将消息放入队列即可。消费者无论何时感觉都会从队列中弹出消息。此操作支持timeout参数。

答案 1 :(得分:1)

正如Simeon在评论中提出的那样,它不能像你在你的例子中描述的那样简单。你需要注意一些细节。根据您的使用情况,有不同的解决方案或多或少有意义。您没有提供有关您真正想做的事情的详细信息,因此我将以http://twistedmatrix.com/trac/wiki/QTReactor为例向您发送信息。有一个不同的解决方案/框架实现异步消息队列。而且我认为,这就是你要找的东西。

答案 2 :(得分:1)

如果您控制生成器函数,一个解决方案是在超时期限后抛出异常。也许有些事情如下:

def get_stream(timeout=None):
    while message=read_message(timeout=timout):
        yield message

然后,如果发生超时条件,read_message会抛出一个TimeOutException。

当然,您仍然需要处理何时/如何重试/恢复的后勤工作。

答案 3 :(得分:0)

您可以使用自python 3.6 https://www.python.org/dev/peps/pep-0525/起的异步生成器

@bot.command()
async def send_typing(ctx):
    await ctx.trigger_typing()
    await asyncio.sleep(10)
    await ctx.send('End of typing')