sys:1: RuntimeWarning: coroutine was never awaited
Question:
I’m trying to write a request handler to help me send request in async mode. It prompt when I close the python terminal with Ctrl+D or exit()
It shows 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'} )
When I Click Ctrl+D , it prompted
sys:1: RuntimeWarning: coroutine 'RequestHandler.AsyncSend' was never awaited
Is that I shall ignore it? I don’t wanna call await
, as i don’t care if the process is success or not.
In this link "https://xinhuang.github.io/posts/2017-07-31-common-mistakes-using-python3-asyncio.html", it said that "To execute an asynchronous task without await, use loop.create_task() with loop.run_until_complete()", is that wrong then?
Answers:
Try this code:
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())
I think you’re confusing JS async API with Python’s. In Python, when you call a coroutine function it returns a coroutine (similar to an armed generator) but doesn’t schedule it in the event loop. (i.e. doesn’t run/consume it)
You have two options:
1) You can await it via await
or the older yield from
.
2) You can asyncio.create_task(coroutine_function())
. This is the equivalent of calling a promise in JS without giving it a handler or awaiting it.
The warning you’re seeing is telling you that the coroutine didn’t run. it was only created, but not consumed.
As to your code, there are two errors. First urllib is a blocking library, you can’t create a task from it, neither can it be ran asynchronously, take a look at aiohttp.ClientSession
instead.
Second, the warning you’re seeing is probably caused by you calling AsyncSend
synchronously (without awaiting it). Again, in JS this would probably be fine, as everything in JS is async. In Python, you should use one of the two main methods I mentioned above.
If you insist on using a blocking library, you can run it on a different thread so that you don’t block the event loop. As Cloudomation mentioned, to do this. you should use asyncio.run_in_executor(None, lambda: your_urllib_function())
I got the same error with test()
as shown below:
async def test():
print("test")
test() # Here
RuntimeWarning: coroutine ‘test’ was never awaited RuntimeWarning:
Enable tracemalloc to get the object allocation traceback
So, I used asyncio.run() for test()
, then the error above is solved:
import asyncio
async def test():
print("test")
asyncio.run(test()) # Here
I’m trying to write a request handler to help me send request in async mode. It prompt when I close the python terminal with Ctrl+D or exit()
It shows 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'} )
When I Click Ctrl+D , it prompted
sys:1: RuntimeWarning: coroutine 'RequestHandler.AsyncSend' was never awaited
Is that I shall ignore it? I don’t wanna call await
, as i don’t care if the process is success or not.
In this link "https://xinhuang.github.io/posts/2017-07-31-common-mistakes-using-python3-asyncio.html", it said that "To execute an asynchronous task without await, use loop.create_task() with loop.run_until_complete()", is that wrong then?
Try this code:
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())
I think you’re confusing JS async API with Python’s. In Python, when you call a coroutine function it returns a coroutine (similar to an armed generator) but doesn’t schedule it in the event loop. (i.e. doesn’t run/consume it)
You have two options:
1) You can await it via await
or the older yield from
.
2) You can asyncio.create_task(coroutine_function())
. This is the equivalent of calling a promise in JS without giving it a handler or awaiting it.
The warning you’re seeing is telling you that the coroutine didn’t run. it was only created, but not consumed.
As to your code, there are two errors. First urllib is a blocking library, you can’t create a task from it, neither can it be ran asynchronously, take a look at aiohttp.ClientSession
instead.
Second, the warning you’re seeing is probably caused by you calling AsyncSend
synchronously (without awaiting it). Again, in JS this would probably be fine, as everything in JS is async. In Python, you should use one of the two main methods I mentioned above.
If you insist on using a blocking library, you can run it on a different thread so that you don’t block the event loop. As Cloudomation mentioned, to do this. you should use asyncio.run_in_executor(None, lambda: your_urllib_function())
I got the same error with test()
as shown below:
async def test():
print("test")
test() # Here
RuntimeWarning: coroutine ‘test’ was never awaited RuntimeWarning:
Enable tracemalloc to get the object allocation traceback
So, I used asyncio.run() for test()
, then the error above is solved:
import asyncio
async def test():
print("test")
asyncio.run(test()) # Here