[英]Combining multiple infinite generator objects into one generator
目的是從多個游戲手柄讀取輸入並在Python中處理它。 我正在使用evdev庫 。
假設給定的設備對象dev
,可以根據文檔使用dev.read_loop()
函數輕松讀取Gamepad發送的事件。 此函數調用返回調試器告知的generator object
。 然后for
可以使用簡單的for
循環來迭代生成器。 它會阻塞,直到發生新的事件,然后再用for循環中使用的任何代碼處理該事件。
現在,我想使用一個自定義類將事件“流”捆綁到多個游戲手柄上(這更像是為它們分配ID,跟蹤斷開連接等),這就是我的問題所在。 我找不到一種方法來創建這樣的生成器,該生成器將所有Gamepad的事件組合在一起。 游戲手柄對象在列表中給出。
提供的示例代碼嘗試模仿所需的行為,但失敗。 構造函數將打印所有可用的設備,然后對其進行初始化。 方法global_generator()
是我解決此問題的方法。 問題是for device in self.__gamepads
外部for循環永遠不會進行,因為第一個生成器是無限的,因此將始終且僅轉發來自第一個控制器的事件。 我嘗試使用itertools.chain()
但是它們有相同的問題,因為第一個生成器itertools.chain()
無休止。 所以我想要的基本上是:“一旦這n個生成器之一產生結果,就進一步產生它(並因此將它們組合)”。 由於無法同時循環我的設備(即它們的生成器)的問題,我擁有的所有想法(例如創建隊列或其他任何東西)總是會停止。
我已經在文檔中看到了該部分,其中顯示了如何從多個設備讀取數據。 問題是他們總是打印結果,但沒有顯示如何以我想要的方式傳遞結果。
import hardware.ControllerHandler as ch
controller_handler = ch.ControllerHandler()
global_generator = controller_handler.global_generator()
for event in global_generator:
#event = ce.ControllerEvent(event)
print(event)
import evdev
from evdev import InputDevice
import asyncio
class ControllerHandler:
def __init__(self):
print(evdev.list_devices())
self.__gamepads = list(map(InputDevice, evdev.list_devices()))
@property
def gamepads(self):
return self.__gamepads
@property
def count(self):
return len(self.__gamepads)
async def global_generator(self):
for device in self.__gamepads:
async for event in device.async_read_loop():
yield event
因此,預期結果是生成器將返回任何基礎事件,而不僅僅是第一個游戲手柄中的事件。
您可以使用aiostream
庫合並多個異步生成器:
async def global_generator(self):
loops = [device.async_read_loop() for device in self.__gamepads]
async with aiostream.stream.merge(*loops).stream() as merged:
async for event in merged:
yield event
如果您不希望依賴aiostream
,請參閱此答案以獲取有關如何使用純asyncio合並流的說明。
請注意,由於生成的生成器是異步的,因此您需要在協程內部使用async for
對其進行迭代。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.