目前我正在编写一段代码,大量使用python 3.7的asyncio
功能。该代码非常复杂,因此希望我能够正确描述我所面临的问题及其触发的问题。
程序的主入口使用process_*()
调用各种gather
待命对象
await asyncio.gather(self.process_api_events(),...)
基本上所有排队工作的人都在做
async def process_api_events(self):
while True:
api_event = await self.api_events_queue.get(),...)
...
await self.starting(sim_uid)
process_api_events()
发出一个starting
请求,该请求本身是可以等待的。它尝试启动docker容器并等待来自容器的通知。通知的逻辑发生在其他地方(为了简单起见,我将其省略)。
但是,将创建一个Future,该future应该在容器出现后等待来自容器的通知。未来等待300秒。当收到来自容器的通知时,将来的结果将像future.set_result(state.value)
那样设置。
state = await asyncio.wait_for(
future, timeout=CONTAINER_UP_TIMEOUT) # [300 secs]
当然,提起容器可能会失败。没有通知将被发送。因此,整个事件循环挂起。我喜欢使用将来检查容器状态的想法。我有什么选择可以无阻地检查我的未来状态?一个新的事件循环?完全不同的线程?
出于完整性考虑,我还发布了整个starting()
方法
async def starting(self, sim_uid: str):
# start the container
await self.container_crane_heave(sim_uid)
# Create future to wait for container to come up
future = asyncio.get_event_loop().create_future()
async def process_state(state: CoreSimulationState):
logger.warning('calccore_state %s ', state)
if state.in_start_up_set:
if not future.done():
future.set_result(state.value)
if sim_uid not in self.state_processors:
self.state_processors[sim_uid] = []
# once the notification from the container comes in,
# the process_state() will be called
self.state_processors[sim_uid].append(process_state)
state = await asyncio.wait_for(
future, timeout=CONTAINER_UP_TIMEOUT)
if CoreSimulationState(state) == CoreSimulationState.CRASHED:
print('CRASHED!!', state)
return
logger.warning('calccore_state %s ', state)