[英]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())
關於此代碼的注意事項:
g_combine以第一個引發StopIteration的生成器結束
g_combine接受N個生成器
如何正確捕獲異常? 想一想。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.