wvx*_*xvw 25 python python-asyncio
我想我得到了这个错误,因为我的代码调用了asyncio.get_event_loop().run_until_complete(foo())两次.从foo()第二次调用函数开始foo().我的问题是:为什么这会成为问题?我为什么要关心这个循环在运行?
对这个问题进行了编辑,我认为这个编辑模糊了(有些人更喜欢遵循规则而不理解它们,因此从标题中删除了"非法"字样).不幸的是,这会造成混乱.
我不会对错误提出这一事实感到惊讶.我可以追溯到asyncio源头,看看这个图书馆的作者想要这样做,那里没有神秘感.令人费解的部分原因在于库的作者认为在循环已经运行时从事件循环中请求运行某些函数是非法的.
我们可以将问题简化为两个这样的调用,通过案例分析,我们将看到这三种可能性:
现在,是否有任何明智的行为可以解决所有三种情况?对我而言,显而易见的是,这里可能存在或可能存在多种理智行为.例如:
run_until_complete()到第二个函数完成之后的第一个实例之后的代码(因此不会run_until_complete()执行后面的代码.run_until_complete忽略所有其他调用站点.现在,我可以理解这种行为可能不是每个人都想要的.但是,由于这个库决定让程序员控制启动/停止事件循环,它还应该满足这些决策的后果.使多次启动相同循环成为错误会使库代码无法执行此操作,从而降低了库利用的质量和实用性asyncio(例如,确实如此aiohttp).
Mik*_*mov 17
事件循环运行 - 是异步程序的入口点.它管理所有协同程序,任务和回调的运行.在运行循环时没有任何意义:在某种程度上,它就像尝试从同一个已经运行的作业执行程序运行作业执行程序.
既然你有这个问题,我想你可能会误解asyncio的工作方式.请阅读这篇文章 - 它不大并且给出了很好的介绍.
UPD:
在此循环已经运行时,添加要由事件循环运行的多个内容绝对没有问题.你可以等待它来做到这一点:
await coro() # add coro() to be run by event loop blocking flow here until coro() is finished
Run Code Online (Sandbox Code Playgroud)
或创建任务:
asyncio.ensure_future(coro()) # add coro() to be run by event loop without blocking flow here
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,您不需要调用事件循环的方法来使其运行.
事件循环的方法,如run_forever或run_until_complete- 只是一般启动事件循环的方法.
run_until_complete(foo())表示:"添加foo()由事件循环运行并运行事件循环本身直到foo()未完成".
Dia*_*ine 13
一开始就加这一堆代码
!pip install nest_asyncio
import nest_asyncio
nest_asyncio.apply()
Run Code Online (Sandbox Code Playgroud)
nur*_*tin 11
我写下这个不是为了光顾,而是为了解释我们如何处理在事件循环运行时简单地将异步函数排队并同步等待它们的结果不起作用的情况。
run_until_complete不是用于同步运行任意数量的任意异步函数,而是用于运行整个异步程序的主要入口点。这个限制在文档中并不明显。
由于像 aiohttp 这样的库会将它自己的入口点排队以作为服务器运行并使用run_until_completeor阻止循环的同步操作run_forever,因此事件循环已经在运行,您将无法在该事件循环上运行独立的同步操作并等待它是该线程内的结果。
话虽如此,如果您必须从同步上下文中将异步操作排队到正在运行的事件循环中,并像常规函数一样获得它的结果,那可能是不可能的。最好的办法是传入一个同步回调,以便在异步操作完成后调用。这当然会减慢你的事件循环。
处理这种情况的另一种方法是在您正在使用的异步 http 库的启动和清理回调中执行您的代码。下面是一个示例,说明您可以如何实现这一点。
mou*_*afa 11
我遇到了同样的问题,我使用Nest_async或asyncio修复了这个问题
解决方案#1
只需安装该软件包:
pip install nest-asyncio
Run Code Online (Sandbox Code Playgroud)
然后添加这些行:
import nest_asyncio
nest_asyncio.apply()
Run Code Online (Sandbox Code Playgroud)
解决方案#2
如果它不能与 Nest_asyncio 一起使用,请尝试asyncio:
import asyncio
asyncio.set_event_loop(asyncio.new_event_loop())
Run Code Online (Sandbox Code Playgroud)
小智 10
我通过使用nest_async解决了问题
pip install nest_asyncio
Run Code Online (Sandbox Code Playgroud)
并在文件中添加以下行。
import nest_asyncio
nest_asyncio.apply()
Run Code Online (Sandbox Code Playgroud)
使用nest_asyncio对我不起作用,因为然后aiohttp开始抱怨
RuntimeError: Timeout context manager should be used inside a task相反,我决定将所有调用替换为asyncio.run对 this 的调用asyncio_run:
def asyncio_run(future, as_task=True):
"""
A better implementation of `asyncio.run`.
:param future: A future or task or call of an async method.
:param as_task: Forces the future to be scheduled as task (needed for e.g. aiohttp).
"""
try:
loop = asyncio.get_running_loop()
except RuntimeError: # no event loop running:
loop = asyncio.new_event_loop()
return loop.run_until_complete(_to_task(future, as_task, loop))
else:
nest_asyncio.apply(loop)
return asyncio.run(_to_task(future, as_task, loop))
def _to_task(future, as_task, loop):
if not as_task or isinstance(future, Task):
return future
return loop.create_task(future)
Run Code Online (Sandbox Code Playgroud)
次要目标是能够将其asyncio.run视为promise.resolve来自 JS 世界或Task.Wait来自 .NET 世界。
| 归档时间: |
|
| 查看次数: |
29793 次 |
| 最近记录: |