簡體   English   中英

如何將多個阻塞Python生成器復用到一個?

[英]How to multiplex multiple blocking Python generators into one?

請考慮以下偽代碼:

def g_user():
    while True:
        yield read_user_input()

def g_socket():
    while True:
        yield read_socket_input()

def g_combined(gu, gs):
    # should read user or socket input, whichever is available

    while True:
        sel = select(gu, gs)
        if sel.contains(gu):
            yield gu.next()
        if sel.contains(gs):
            yield gs.next()

gc = g_combined ( g_user(), g_socket() )

如何以最簡單的方式實現這一點?

看起來就像有人已經實現了這個: http//www.dabeaz.com/generators/genmulti.py

在這里反映:

import Queue, threading
def gen_multiplex(genlist):
    item_q = Queue.Queue()
    def run_one(source):
        for item in source: item_q.put(item)

    def run_all():
        thrlist = []
        for source in genlist:
            t = threading.Thread(target=run_one,args=(source,))
            t.start()
            thrlist.append(t)
        for t in thrlist: t.join()
        item_q.put(StopIteration)

    threading.Thread(target=run_all).start()
    while True:
        item = item_q.get()
        if item is StopIteration: return
        yield item

為了使select.select()正常工作,您需要在生成器上公開一個返回底層文件描述符的fileno()方法。

標准庫中的itertools模塊包含很好的函數。 在這種特定情況下,循環功能很好。

循環幫助說:

cycle(iterable) - >循環對象

從迭代中返回元素直到它耗盡。 然后無限期地重復該序列。

在解決方案中使用循環:

import itertools

def g_user():
    while True:
        yield read_user_input()

def g_socket():
    while True:
        yield read_socket_input()


def g_combine(*generators):
    for generator in itertools.cycle(generators):
        yield generator.next()


g_combined =  g_combine(g_user(), g_socket())

關於此代碼的注意事項:

  1. g_combine以第一個引發StopIteration的生成器結束

  2. g_combine接受N個生成器

  3. 如何正確捕獲異常? 想一想。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM