Python asncio coroutine从未被期待过

Python asncio coroutine从未被期待过,python,python-asyncio,Python,Python Asyncio,我正在尝试运行一个带有asyncio的2个协程的实验。一个循环是刮取气温以外的天气数据,另一个循环只是一个带有numpy random的虚构值。两个协同程序都有相同的回溯,没有任何事情发生 运行时警告:从未等待协同程序“获取天气” 有人有什么想法可以试试吗?我试着用这个来回答一个类似的问题,也试着用我正在做的协同程序来运行Python3.7 import asyncio import requests from bs4 import BeautifulSoup import pandas as

我正在尝试运行一个带有asyncio的2个协程的实验。一个循环是刮取气温以外的天气数据,另一个循环只是一个带有numpy random的虚构值。两个协同程序都有相同的回溯,没有任何事情发生

运行时警告:从未等待协同程序“获取天气”

有人有什么想法可以试试吗?我试着用这个来回答一个类似的问题,也试着用我正在做的协同程序来运行Python3.7

import asyncio
import requests
from bs4 import BeautifulSoup
import pandas as pd
import numpy as np


headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'}

async def get_weather():
    await asyncio.sleep(300)

    r = requests.get('https://www.google.com/search?q=weather%20duluth', headers=headers)
    soup = BeautifulSoup(r.text, 'html.parser')
    outTemp = soup.find("span", {"class": "wob_t"}).text
    intOutTemp = int(outTemp)
    print(f'got outside temperature data {intOutTemp}')
    return intOutTemp


async def get_temp():
    await asyncio.sleep(10)

    inTemp = (random.random() * 20) - 5  # -5 to 15
    print(f'got inside temperature data {inTemp}')
    return temperature


def main():
    loop1 = get_weather()
    loop2 = get_temp()



if __name__ == '__main__':
    main()
更新代码


您刚刚创建了一个名为loop1&loop2的变量。他们都不等待任务完成。要将asyncio.run用作入口点,可以将异步方法传入asyncio.gather方法,以等待两个任务完成

要在无限循环中运行方法,可以使用while True:方法,而不是从该方法返回。我建议将逻辑分为两种方法,或者将GetWeather重命名为GetWeather之类的方法。它可以让其他用户在不查看逻辑的情况下了解代码的功能

另外,request.get不会并行运行。谷歌立即返回结果。但是,如果您将URL指向等待时间较长的某个地方,则问题是显而易见的。因此,我强烈建议使用aiohttp

此外,Windows上还有一个问题,aiohttp.get会抛出一个错误事件循环并关闭。因此,作为在上找到的解决方法。因此,我添加了注释掉的代码,在asyncio.run之前调用asyncio.set\u event\u loop\u policy asyncio.WindowsSelectorEventLoopPolicy。只有在你需要的时候才使用它

下面是一个工作示例:

import asyncio
import aiohttp
from bs4 import BeautifulSoup
import json
import pandas as pd
import numpy as np
import random

headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'}

def Logger(json_message):
    print(json.dumps(json_message))

async def get_weather():
    Logger({"start": "get_weather()"})
    while True:
        await asyncio.sleep(3)    
        async with aiohttp.ClientSession() as session:
            r = await session.get('https://www.google.com/search?q=weather%20duluth', headers=headers)
            soup = BeautifulSoup(await r.text(), 'html.parser')
            outTemp = soup.find("span", {"class": "wob_t"}).text
            intOutTemp = int(outTemp)

            Logger({"results": f'got outside temperature data {intOutTemp}'})
            Logger({"finish": "get_weather()"})
            #return intOutTemp # without a return, the while loop will run continuously.

async def get_temperature():
    Logger({"start": "get_temperature()"})
    while True:
        await asyncio.sleep(1)

        inTemp = (random.random() * 20) - 5  # -5 to 15
        Logger({"results": f'got inside temperature data {inTemp}'})
        Logger({"finish": "get_temperature()"})
        #return inTemp # without a return, the while loop will run continuously.

async def main():
    statements = [get_weather(), get_temperature()]
    Logger({"start": "gather()"})

    await asyncio.gather(*statements) # Gather is used to allow both funtions to run at the same time.
    Logger({"finish": "gather()"})

if __name__ == '__main__':
    #asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) # Use this to stop "Event loop is closed" error on Windows - https://github.com/encode/httpx/issues/914
    asyncio.run(main())

@格雷格:谢谢你的回复。这个脚本可以工作,但是你知道我如何让脚本在无限循环中运行吗?我添加了一些while True语句并调整了ascio睡眠时间。。。在我更新代码的帖子中,它似乎正在运行,但没有打印任何值。。。您有什么想法让代码在内部运行吗?我刚刚更新了代码,为asyncio.run添加了一个条目。脚本应该只打印一次。无限期运行代码的一种可能性是在main完成后调用main。我不知道你为什么要那样做?谢谢你的帮助。。你能告诉我使用请求和aiohttp的区别吗?格雷格,谢谢你回复我的评论,非常感谢!不过,我怀疑HenryHub会失望地注意到对requests.get in get_weather和get_temp中的任何内容的调用实际上并没有并行运行。get\u weather应该使用aiohttp来获取数据,或者至少使用loop.run\u in\u executor来执行请求。脱离线程,允许事件循环继续执行其他协同程序。@user4815162342看起来aiohttp中有一个错误,事件循环被关闭,所以我将请求放回了。get-in。就像你提到的,有一些很好的解决办法。获取天气和获取温度应并行运行。如果您将超时时间更改为10秒,添加一些打印语句,您应该可以看到它们同时运行。
import asyncio
import aiohttp
from bs4 import BeautifulSoup
import json
import pandas as pd
import numpy as np
import random

headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'}

def Logger(json_message):
    print(json.dumps(json_message))

async def get_weather():
    Logger({"start": "get_weather()"})
    while True:
        await asyncio.sleep(3)    
        async with aiohttp.ClientSession() as session:
            r = await session.get('https://www.google.com/search?q=weather%20duluth', headers=headers)
            soup = BeautifulSoup(await r.text(), 'html.parser')
            outTemp = soup.find("span", {"class": "wob_t"}).text
            intOutTemp = int(outTemp)

            Logger({"results": f'got outside temperature data {intOutTemp}'})
            Logger({"finish": "get_weather()"})
            #return intOutTemp # without a return, the while loop will run continuously.

async def get_temperature():
    Logger({"start": "get_temperature()"})
    while True:
        await asyncio.sleep(1)

        inTemp = (random.random() * 20) - 5  # -5 to 15
        Logger({"results": f'got inside temperature data {inTemp}'})
        Logger({"finish": "get_temperature()"})
        #return inTemp # without a return, the while loop will run continuously.

async def main():
    statements = [get_weather(), get_temperature()]
    Logger({"start": "gather()"})

    await asyncio.gather(*statements) # Gather is used to allow both funtions to run at the same time.
    Logger({"finish": "gather()"})

if __name__ == '__main__':
    #asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) # Use this to stop "Event loop is closed" error on Windows - https://github.com/encode/httpx/issues/914
    asyncio.run(main())