我正在寻找一种在程序中经常出现的构造的pythonic asyncio“模式”。
工作者任务执行一些通常由几个步骤组成的操作。这些操作的详细信息由从控制功能发送到工作人员任务的命令控制。在各个步骤之间存在睡眠,并且工作人员仅在这些睡眠期间才能接受新命令。一个新命令应立即将工作者任务从睡眠中唤醒。
命令表示所需的目标状态。我正在使用队列进行通信。但是,只能有一个目标,这就是为什么这些命令不建立真实队列的原因,而最后一个替换了之前的所有队列。队列中最多只有一个项目。
目前,我正在使用其他异步库。我想切换到标准asyncio
。一个例子:
# warning: not asyncio code; not real code
cmd_queue = Queue()
async def worker():
cmd = 'INIT'
while cmd != 'STOP':
... do_something1 sync or async ...
newcmd = await cmd_queue.get(timeout=SLEEPTIME1, timeout_value=None)
if newcmd is not None:
cmd = newcmd
continue
... do_something2 sync or async ...
newcmd = await cmd_queue.get(timeout=SLEEPTIME2, timeout_value=None)
if newcmd is not None:
cmd = newcmd
continue
def controlloler():
...
if newcmd:
cmd_queue.clear() # replaces a waiting command
cmd_queue.put(newcmd) # put_nowait() in asyncio
...
我可以将queue.get
的形式重写为异步代码:
try:
cmd=wait_for(cmd_queue.get(), timeout=SLEEPTIME)
continue # or process otherwise
except asyncio.TimeoutError:
pass
但是我认为也许有一个更简单的解决方案。 OTOH如果您有异步的经验,并且认为超时是一个可行的方法,那对我也有帮助。
我尝试搜索,但是找不到适合我的问题的关键字(问题标题也是如此)。
答案 0 :(得分:1)
您的超时实现肯定没有错。异步synchronization原语上的方法有意不支持显式的超时参数,将其留给调用方使用取消或wait_for
可以在需要时超时。
对于单元素队列,我会考虑用Future
替换它,该队列不仅被设计为保存单个值,而且由于它是用于构建几乎所有其他内容。
您将写wait_for(cmd_queue.get(), ...)
而不是wait_for(cmd_future, ...)
,而是写cmd_queue.put(value)
而不是cmd_future.set_result(value)
。唯一重要的区别是前途是一次性的,因此在获得物品后,您需要为cmd_future
分配新的前途。