Python3.6的错误: AttributeError: module 'asyncio'没有'run'属性

95

我尝试阅读https://hackernoon.com/asynchronous-python-45df84b82434,这篇文章讲解了Python异步编程,我尝试运行其中的代码,但是出现了奇怪的错误。代码如下:

`
import asyncio
import aiohttp

urls = ['http://www.google.com', 'http://www.yandex.ru', 'http://www.python.org']

async def call_url(url):
    print('Starting {}'.format(url))
    response = await aiohttp.ClientSession().get(url)
    data = await response.text()
    print('{}: {} bytes: {}'.format(url, len(data), data))
    return data

futures = [call_url(url) for url in urls]

asyncio.run(asyncio.wait(futures))

当我尝试运行它时,会显示:

Traceback (most recent call last):
  File "test.py", line 15, in <module>
    asyncio.run(asyncio.wait(futures))
AttributeError: module 'asyncio' has no attribute 'run'
sys:1: RuntimeWarning: coroutine 'call_url' was never awaited

我没有任何名为ayncio的文件,这是我的证明:

>>> asyncio
<module 'asyncio' from '/usr/lib/python3.6/asyncio/__init__.py'>
4个回答

122

asyncio.run 是 Python 3.7 新增的内容。在 3.5-3.6 中,您的示例大致等同于:

import asyncio

futures = [...]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(futures))

10
当你获取现有的事件循环时,不要关闭它。asyncio.run()仅在实际创建一个新的事件循环启动时才会关闭循环。 - Martijn Pieters
你可能想使用 asyncio.gather 而不是 asyncio.wait 来真正消耗future并处理异常。 - mkaptur
当我尝试这样做时,实际上无法访问后续行中的期货内容。我只得到print(str(futures))[<coroutine object myfun at 0x123123123>],似乎就是这样。我该如何获取实际调用期货内部函数的输出呢? - undefined

56

asyncio.run()函数是在Python 3.7中添加的。根据asyncio.run()函数文档

3.7版本新增:重要提示:此功能已经作为试验功能添加到Python 3.7的asyncio中。

请注意试验功能部分;Python维护人员认为该功能可能需要进一步调整和更新,因此API可能会在未来的Python版本中进行更改。

无论如何,在Python 3.6上都不能使用它。您必须升级或者自己实现一个类似的函数。

一个非常简单的近似方法是使用loop.run_until_complete()函数:

loop = asyncio.get_event_loop()
result = loop.run_until_complete(coro)

虽然这忽略了处理可能仍在运行的剩余任务。请参见asyncio.runners源代码,以获取完整的asyncio.run()实现。


11

如果有其他人有类似的问题,这可能会对你有所帮助。我的文件名叫做asyncio.py 。我将其重命名为asyncio_example.py ,然后它又开始正常工作了(在导入asycnio模块时之前它一直执行失败)。

这个问题让我认识到了这一点:https://github.com/tornadoweb/tornado/issues/2868


1
谢谢你的解决方案。这也解决了我的问题。 - Jaylin
我将我的模块命名为“socket.py”,并遇到了相同的问题。 - Konrads
这真是救了我! - Alexander Knight Room

0

如果有人遇到没有当前循环的问题,请尝试:

loop = asyncio.**new**_event_loop()

result = loop.run_until_complete(coro)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接