Nei*_*eil 6 python python-asyncio
我在我的asyncio事件循环上设置了一个异常处理程序。但是,它似乎直到事件循环线程停止后才被调用。例如,考虑以下代码:
def exception_handler(loop, context):
print('Exception handler called')
loop = asyncio.get_event_loop()
loop.set_exception_handler(exception_handler)
thread = Thread(target=loop.run_forever)
thread.start()
async def run():
raise RuntimeError()
asyncio.run_coroutine_threadsafe(run(), loop)
loop.call_soon_threadsafe(loop.stop, loop)
thread.join()
Run Code Online (Sandbox Code Playgroud)
如我们所料,此代码将显示“已调用异常处理程序”。但是,如果我删除关闭事件循环(loop.call_soon_threadsafe(loop.stop, loop))的行,它将不再打印任何内容。
我对此有一些疑问:
我在这里做错什么了吗?
有谁知道这是否是asyncio异常处理程序的预期行为?我找不到任何可以证明这一点的文件,这对我来说似乎有点奇怪。
我非常希望有一个长时间运行的事件循环,该循环记录其协程中发生的错误,因此当前行为对我来说似乎是有问题的。
上面的代码有几个问题:
stop() 不需要参数stop()在它之前被调用)。这是固定代码(无异常和异常处理程序):
import asyncio
from threading import Thread
async def coro():
print("in coro")
return 42
loop = asyncio.get_event_loop()
thread = Thread(target=loop.run_forever)
thread.start()
fut = asyncio.run_coroutine_threadsafe(coro(), loop)
print(fut.result())
loop.call_soon_threadsafe(loop.stop)
thread.join()
Run Code Online (Sandbox Code Playgroud)
call_soon_threadsafe() 返回一个保存异常的未来对象(它不会到达默认的异常处理程序):
import asyncio
from pprint import pprint
from threading import Thread
def exception_handler(loop, context):
print('Exception handler called')
pprint(context)
loop = asyncio.get_event_loop()
loop.set_exception_handler(exception_handler)
thread = Thread(target=loop.run_forever)
thread.start()
async def coro():
print("coro")
raise RuntimeError("BOOM!")
fut = asyncio.run_coroutine_threadsafe(coro(), loop)
try:
print("success:", fut.result())
except:
print("exception:", fut.exception())
loop.call_soon_threadsafe(loop.stop)
thread.join()
Run Code Online (Sandbox Code Playgroud)
但是,使用create_task()或ensure_future()将调用 exception_handler 调用的协程:
async def coro2():
print("coro2")
raise RuntimeError("BOOM2!")
async def coro():
loop.create_task(coro2())
print("coro")
raise RuntimeError("BOOM!")
Run Code Online (Sandbox Code Playgroud)
您可以使用它来创建一个小包装器:
async def boom(x):
print("boom", x)
raise RuntimeError("BOOM!")
async def call_later(coro, *args, **kwargs):
loop.create_task(coro(*args, **kwargs))
return "ok"
fut = asyncio.run_coroutine_threadsafe(call_later(boom, 7), loop)
Run Code Online (Sandbox Code Playgroud)
但是,您可能应该考虑使用队列与您的线程进行通信。
| 归档时间: |
|
| 查看次数: |
1898 次 |
| 最近记录: |