是什么导致asyncio.new_event_loop()的简单调用挂起? [英] What can cause the simple invocation of asyncio.new_event_loop() to hang?
问题描述
我正在使用以下功能来强制协程同步运行:
I am using the following function to force a coroutine to run synchronously:
import asyncio
import inspect
import types
from asyncio import BaseEventLoop
from concurrent import futures
def await_sync(coro: types.CoroutineType, timeout_s: int=None):
"""
:param coro: a coroutine or lambda loop: coroutine(loop)
:param timeout_s:
:return:
"""
loop = asyncio.new_event_loop() # type: BaseEventLoop
if not is_awaitable(coro):
coro = coro(loop)
if timeout_s is None:
fut = asyncio.ensure_future(coro, loop=loop)
else:
fut = asyncio.ensure_future(asyncio.wait_for(coro, timeout=timeout_s, loop=loop), loop=loop)
loop.run_until_complete(fut)
return fut.result()
def is_awaitable(coro_or_future):
if isinstance(coro_or_future, futures.Future):
return coro_or_future
elif asyncio.coroutines.iscoroutine(coro_or_future):
return True
elif asyncio.compat.PY35 and inspect.isawaitable(coro_or_future):
return True
else:
return False
但是,间歇性地,它只会在尝试创建一个新值时冻结循环: loop = asyncio.new_event_loop()
。检查堆栈跟踪会向我显示其挂起的确切位置:
However, intermittently, it will freeze upon simply trying to create a new loop: loop = asyncio.new_event_loop()
. Inspecting the stack traces shows me the exact location where it hangs:
File: "/src\system\utils.py", line 34, in await_sync
loop = asyncio.new_event_loop() # type: BaseEventLoop
File: "\lib\asyncio\events.py", line 636, in new_event_loop
return get_event_loop_policy().new_event_loop()
File: "\lib\asyncio\events.py", line 587, in new_event_loop
return self._loop_factory()
File: "\lib\asyncio\selector_events.py", line 55, in __init__
self._make_self_pipe()
File: "\lib\asyncio\selector_events.py", line 116, in _make_self_pipe
self._ssock, self._csock = self._socketpair()
File: "\lib\asyncio\windows_events.py", line 295, in _socketpair
return windows_utils.socketpair()
File: "\lib\socket.py", line 515, in socketpair
ssock, _ = lsock.accept()
File: "\lib\socket.py", line 195, in accept
fd, addr = self._accept()
什么ca是在 socket
这样低级的库中引起这种问题的吗?难道我做错了什么?我正在使用Python 3.5.1。
What can be causing such an issue, in a library as low level as socket
? Am I doing something wrong? I am using Python 3.5.1.
编辑:我提交了错误报告此处,但Guido建议我继续在StackOverflow上寻求帮助。
I filed a bug report here but Guido recommended me to continue seeking help on StackOverflow.
推荐答案
我正试图了解您要做什么。
I'm trying to understand what you are trying to do.
如果我正确理解它,那么无论输入是协程还是简单的函数调用,您都希望有一个函数可以返回相同的结果。如果我是对的,那么这似乎很好。
If I get it correctly you want a function that will return the same thing whether the input is a coroutine or a simple function call. If I'm correct, then this seems to work fine.
import asyncio
import time
def await_sync(coro, timeout=None):
if asyncio.iscoroutine(coro):
f = asyncio.wait_for(coro, timeout)
loop = asyncio.get_event_loop()
return loop.run_until_complete(f)
return coro
async def async_test(x):
print("x", end="")
await asyncio.sleep(x)
print("y", end="")
return x
def sync_test(x):
print("x", end="")
time.sleep(x)
print("y", end="")
return x
print(await_sync(sync_test(2)))
print(await_sync(async_test(3)))
这将输出以下结果(我猜是预期的):
This outputs the following (I guess expected) result:
xy2
xy3
这篇关于是什么导致asyncio.new_event_loop()的简单调用挂起?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!