sys: 1: RuntimeWarning: сопрограмма никогда не ожидалась - PullRequest
1 голос
/ 19 апреля 2019

Я пытаюсь написать обработчик запроса, чтобы помочь мне отправить запрос в асинхронном режиме.Он запрашивает, когда я закрываю терминал python с помощью Ctrl + D или exit ()

Он показывает 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 () ", тогда это неправильно?

Ответы [ 2 ]

3 голосов
/ 20 апреля 2019

Я думаю, что вы путаете JS async API с Python. В 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())

1 голос
/ 19 апреля 2019

Попробуйте этот код:

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