sys:1: RuntimeWarning: coroutine was never awaited

2019-09-29 05:02发布

我试图写一个请求处理程序,以帮助我送在异步模式下请求。 它提示当我关闭用Ctrl + d或退出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 ”,它说:“要没有的await执行异步任务,使用循环。 create_task()与loop.run_until_complete()”,是错的呢?

Answer 1:

我想你混淆了Python的JS异步API。 在Python中,当你调用一个函数协程,它返回一个协程(类似于武装发电机),但在事件循环不安排它。 (即不运行/消耗它)

你有两个选择:

1)您可以通过它等待await或上了年纪yield from

2)你可以asyncio.create_task(coroutine_function()) 这是调用JS承诺没有给它一个句柄或等待它的等价物。

你看到的警告,告诉您协同程序没有运行。 它不仅创造,而不是消费。

至于你的代码中,有两个错误。 首先的urllib是阻塞库,你不能从它创建任务,既可以在异步运行,看看aiohttp.ClientSession代替。

其次,你所看到的警告由你打电话很可能造成AsyncSend同步(无需等待它)。 再次,在JS这可能会被罚款,因为一切都在JS是异步。 在Python中,你应该使用我上面提到的两种主要方法之一。

如果你坚持使用阻塞库,你可以在不同的线程中运行它,这样你就不会阻塞事件循环。 作为Cloudomation提到,要做到这一点。 你应该使用asyncio.run_in_executor(None, lambda: your_urllib_function())



Answer 2:

试试这个代码:

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())


文章来源: sys:1: RuntimeWarning: coroutine was never awaited