我正在尝试编写一个请求处理程序来帮助我以异步模式发送请求。当我使用 Ctrl+D 或 exit() 关闭 python 终端时它会提示
它显示 sys:1: RuntimeWarning: coroutine was never awaited
import asyncio
import urllib.request
import json
class RequestHandler:
def SendPostRequest(method="post",url=None, JsonFormatData={}):
# Encode JSON
data =json.dumps(JsonFormatData).encode('utf8')
# Config Request Header
req = urllib.request.Request(url)
req.add_header('Content-Type', 'application/json')
# Send request and wait the response
response = urllib.request.urlopen(req,data=data)
return response
async def AsyncSend(method="post",url=None, JsonFormatData=None):
if method == "post":
loop = asyncio.get_event_loop()
task = loop.create_task(SendPostRequest(method="post",url=url,JsonFormatData=JsonFormatData))
###################################
# Example
##### In main python terminal, i run like this:
# from RequestHandler import *
# RequestHandler.AsyncSend(method="post",url="xxxxxx", JsonFormatData={'key':'value'} )
当我点击 Ctrl+D 时,它提示
sys:1: RuntimeWarning: coroutine 'RequestHandler.AsyncSend' was never awaited
那是我要忽略它吗?我不想打电话 await
,因为我不在乎这个过程是否成功。
在这个链接“https://xinhuang.github.io/posts/2017-07-31-common-mistakes-using-python3-asyncio.html”中,它说“要在没有等待的情况下执行异步任务,请使用循环。 create_task() 和 loop.run_until_complete()”,是不是错了?
原文由 Question-er XDD 发布,翻译遵循 CC BY-SA 4.0 许可协议
我认为您将 JS 异步 API 与 Python 混淆了。在 Python 中,当您调用协程函数时,它会返回一个协程(类似于武装生成器),但不会在事件循环中安排它。 (即不运行/消耗它)
你有两个选择:
您可以通过
await
或更旧的yield from
等待它。你可以
asyncio.create_task(coroutine_function())
。这相当于在 JS 中调用一个 promise 而不给它一个处理程序或等待它。您看到的警告告诉您协程没有运行。它只是被创建,但没有被消费。
至于你的代码,有两个错误。首先 urllib 是一个阻塞库,你不能从它创建任务,也不能异步运行,看看
aiohttp.ClientSession
代替。其次,您看到的警告可能是由于您同步调用
AsyncSend
引起的(没有等待)。同样,在 JS 中这可能没问题,因为 JS 中的所有内容都是异步的。在 Python 中,您应该使用我上面提到的两种主要方法之一。如果你坚持使用阻塞库,你可以在不同的线程上运行它,这样你就不会阻塞事件循环。正如 Cloudomation 提到的那样,要做到这一点。你应该使用
asyncio.run_in_executor(None, lambda: your_urllib_function())