在不同的事件循环中比赛两个任务

2024-10-02 08:15:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用的是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()

不幸的是,我一直收到以下错误:

^{pr2}$

似乎我无法与等待任务竞争,因为它属于另一个循环。有没有什么方法可以避免这个错误,这样我就可以确定哪个任务首先完成?在


Tags: dockerrunnoneloopasynciotaskreturncontainer
1条回答
网友
1楼 · 发布于 2024-10-02 08:15:31

问题很简单,每个线程都有一个默认循环。由asyncio.set_event_loop(loop)设置。然后您可以通过loop = asyncio.get_event_loop()得到这个循环。在

所以问题是,大多数情况下,一些包默认使用asyncio.get_event_loop()来获取当前运行的循环。以aiohttp为例:

class aiohttp.ClientSession(*, connector=None, loop=None, cookies=None, headers=None, skip_auto_headers=None, auth=None, json_serialize=json.dumps, version=aiohttp.HttpVersion11, cookie_jar=None, read_timeout=None, conn_timeout=None, timeout=sentinel, raise_for_status=False, connector_owner=True, auto_decompress=True, requote_redirect_url=False, trust_env=False, trace_configs=None)

如您所见,它接受loop参数来指定正在运行的循环。但您也可以将其留空以默认使用asyncio.get_event_loop()。在

你的问题是在一个新创建的循环中启动协同程序。但你不能确认你所有的内部行动也在使用这个新创造的。由于它们可能使用asyncio.get_event_loop(),它们将被附加到另一个循环中,这是当前线程中的默认循环。在


据我所知,你不需要创建一个新的,但是让用户去做。与上面的例子一样,您接受一个参数loop,如果它是None,那么使用默认参数。在


或者您需要仔细检查代码,以确保每个可能的协同程序都在使用您创建的循环。在

相关问题 更多 >

    热门问题