【发布时间】:2019-01-27 18:34:22
【问题描述】:
我正在使用 Docker SDK,我正在尝试将一个在几秒后超时的任务与另一个等待 Docker 容器完成的任务进行竞争。实际上,我想知道给定容器是否在我设置的超时时间内完成。
我有以下代码(改编自this post):
container = # ... create container with Docker SDK
timeout = # ... some int
killed = None
# our tasks
async def __timeout():
await asyncio.sleep(timeout)
return True
async def __run():
container.wait()
return False
# loop and runner
wait_loop = asyncio.new_event_loop()
done, pending = wait_loop.run_until_complete(
asyncio.wait({__run(), __timeout()}, return_when=asyncio.FIRST_COMPLETED)
)
# result extraction
for task in done:
if killed is None:
killed = task.result()
# ... do something with result
# clean up
for task in pending:
task.cancel()
with contextlib.suppress(asyncio.CancelledError):
wait_loop.run_until_complete(task)
wait_loop.close()
很遗憾,我不断收到以下错误:
File "/usr/lib/python3.5/asyncio/base_events.py", line 387, in run_until_complete
return future.result()
File "/usr/lib/python3.5/asyncio/futures.py", line 274, in result
raise self._exception
File "/usr/lib/python3.5/asyncio/tasks.py", line 241, in _step
result = coro.throw(exc)
File "/usr/lib/python3.5/asyncio/tasks.py", line 347, in wait
return (yield from _wait(fs, timeout, return_when, loop))
File "/usr/lib/python3.5/asyncio/tasks.py", line 430, in _wait
yield from waiter
File "/usr/lib/python3.5/asyncio/futures.py", line 361, in __iter__
yield self # This tells Task to wait for completion.
RuntimeError: Task <Task pending coro=<wait() running at /usr/lib/python3.5/asyncio/tasks.py:347> cb=[_run_until_complete_cb() at /usr/lib/python3.5/asyncio/base_events.py:164]> got Future <Future> pending> attached to a different loop
似乎我无法与等待任务竞争,因为它属于不同的循环。有什么办法可以绕过这个错误,以便我可以确定哪个任务先完成?
【问题讨论】:
-
你有Debug Mode ON,只是想看看发生了什么?
-
我没有看到调试模式,只是一个分析器。这对解决这样的异步问题有帮助吗?
-
文档中提到了调试模式。用法:
asyncio.run(main(), debug=True)。这很有帮助,尽管分析也有帮助。 -
你究竟为什么要创建一个新的事件循环?您实际上有两个循环可以在任何时候使用吗? (您可能不应该。)如果您需要创建新的事件循环,请尝试尽早创建它并使用
asyncio.set_event_loop(wait_loop)让 asyncio 意识到它。 -
最终我创建了一个新的事件循环,因为我认为我需要这样做。我正在尝试将这部分作为模块的一部分,所以我不能确定我的模块的用户也不会创建一个事件循环。
标签: python python-asyncio