我正在尝试编写一个请求处理程序,以帮助我以异步模式发送请求。当我使用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”中,它表示“要在不等待的情况下执行异步任务,请将loop.create_task()与loop.run_until_complete()一起使用”,那是错误的吗?
答案 0 :(得分:3)
我认为您正在将JS异步API与Python混淆。在Python中,当您调用协程函数时,它会返回协程(类似于武装生成器),但不会在事件循环中对其进行调度。 (即不运行/消费)
您有两个选择:
1)您可以通过await
或更旧的yield from
等待它。
2)您可以asyncio.create_task(coroutine_function())
。这等效于在JS中调用promise而不给其处理程序或等待它。
您看到的警告是告诉您协程未运行。它仅被创建,未被消耗。
关于您的代码,有两个错误。首先urllib是一个阻塞库,您无法从中创建任务,也不能异步运行它,而请查看aiohttp.ClientSession
。
第二,您看到的警告可能是由于您同步调用AsyncSend
(没有等待它)引起的。同样,在JS中这可能很好,因为JS中的所有内容都是异步的。在Python中,您应该使用我上面提到的两种主要方法之一。
如果您坚持使用阻塞库,则可以在其他线程上运行它,以免阻塞事件循环。正如Cloudomation所提到的,要做到这一点。您应该使用asyncio.run_in_executor(None, lambda: your_urllib_function())
答案 1 :(得分:1)
尝试以下代码:
class RequestHandler:
def SendPostRequest(self, 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 Send(self, method="post", url=None, JsonFormatData=None):
if method == "post":
bound = functools.partial(self.SendPostRequest, method="post", url=url, JsonFormatData=JsonFormatData)
loop = asyncio.get_event_loop()
await loop.run_in_executor(None, bound)
def SendAsync(self):
loop = asyncio.get_event_loop()
loop.create_task(self.Send())