sys:1: RuntimeWarning: 从未等待协程

新手上路,请多包涵

我正在尝试编写一个请求处理程序来帮助我以异步模式发送请求。当我使用 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 许可协议

阅读 5.2k
2 个回答

我认为您将 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())

原文由 Charming Robot 发布,翻译遵循 CC BY-SA 4.0 许可协议

试试这个代码:

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

原文由 Cloudomation 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题