【问题标题】:Problem in using async and await in python在 python 中使用 async 和 await 的问题
【发布时间】:2021-02-23 06:05:20
【问题描述】:

我正在尝试使用异步和等待,我还是新手,我不知道我做错了什么

import requests
import bs4
import colorama
from colorama import Fore
import time
import datetime
import asyncio



async def get_html(episode_number: int) -> str:
    print(Fore.YELLOW + f"Getting HTML for episode {episode_number}", flush=True)

    url = f'https://talkpython.fm/{episode_number}'
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as resp:
            resp.raise_for_status()
            return await resp.text
    await resp.raise_for_status()
   # return await resp.text


def get_title(html: str, episode_number: int) -> str:
    print(colorama.Fore.CYAN + f"Getting TITLE for episode {episode_number}", flush=True)
    soup = bs4.BeautifulSoup(html, 'html.parser')
    header = soup.select_one('h1')
    if not header:
        return "MISSING"

    return header.text.strip()


def main():

    t0 = datetime.datetime.now()
    print(colorama.Fore.WHITE + ' App started.', flush=True )

    loop = asyncio.get_event_loop()
    final_task = asyncio.gather(loop)
    #get_title_range()
    dt = datetime.datetime.now() - t0
    loop.run_until_complete(final_task)
    print(colorama.Fore.CYAN + "Done. " + ' App exiting total time: {:,.2f} sec.'.format(dt.total_seconds()), flush=True)


def get_title_range():
  
    for n in range(150, 170):
        html = get_html(n)
        title = get_title(html, n)
        print(Fore.CYAN + f"Title found: {title}", flush=True)


if __name__ == '__main__':
    main()

【问题讨论】:

标签: python async-await


【解决方案1】:

您似乎没有为要运行的事件循环初始化任务。我通常遵循这种模式:

async def main():
    headers = {'Connection': 'keep-alive', 'Content-Type': 'application/json', 'Authorization': auth}
    url = 'some-api.com/post-request-something'

    # We use a session to take advantage of tcp keep-alive
    timeout = aiohttp.ClientTimeout(total=10000)
    async with aiohttp.ClientSession(timeout=timeout) as session:
        tasks = [async_wrap(session, q, url, headers) for q in queue]
        # gather literally 'gathers' all the tasks and schedules them in the event loop
        await asyncio.gather(*tasks, return_exceptions=True)

if __name__ == '__main__':
    ts = time()
    # Create the asyncio event loop - from the main function
    loop = asyncio.get_event_loop()
    try:
        loop.run_until_complete(main())
    finally:
        # Lets avoid an unclosed loop running a DDoS attack on ourselves
        loop.close()
    logger.info('Took %s seconds to complete', time() - ts)

注意包含的行,将收集到的任务作为协程安排在主事件循环中:

loop.run_until_complete(main())

然后这个,它调用我的函数, async_wrap() 用于我想在http客户端中发送的每条记录(我存储在一个列表中),但在你的情况下,它会调用你的异步函数 get_html() 使用get_title_range() 中的每条记录:

tasks = [async_wrap(session, q, url, headers) for q in queue] # -> mine
await asyncio.gather(*tasks, return_exceptions=True) # -> gather those tasks!

tasks = [get_html(episode_number=episode) for episode in list_of_episode_nums] # -> yours
await asyncio.gather(*tasks, return_exceptions=True) # -> gather those tasks!

希望这可以帮助您巩固一些细节,但不幸的是,异步代码可能会让人头疼,需要大量的反复试验。

【讨论】:

    猜你喜欢
    • 2020-03-25
    • 1970-01-01
    • 2019-04-30
    • 1970-01-01
    • 1970-01-01
    • 2020-12-19
    • 2015-08-21
    • 1970-01-01
    • 2016-07-05
    相关资源
    最近更新 更多