簡體   English   中英

如何管理單個aiohttp.ClientSession?

[英]How to manage a single aiohttp.ClientSession?

作為一個學習練習,我正在嘗試修改aiohttp的快速啟動示例以使用單個ClientSession獲取多個URL(文檔建議通常應為每個應用程序創建一個ClientSession)。

import aiohttp
import asyncio

async def fetch(session, url):
  async with session.get(url) as response:
    return await response.text()

async def main(url, session):
  print(f"Starting '{url}'")
  html = await fetch(session, url)
  print(f"'{url}' done")

urls = (
  "https://python.org",
  "https://twitter.com",
  "https://tumblr.com",
  "https://example.com",
  "https://github.com",
)

loop = asyncio.get_event_loop()
session = aiohttp.ClientSession()
loop.run_until_complete(asyncio.gather(
  *(loop.create_task(main(url, session)) for url in urls)
))
# session.close()   <- this doesn't make a difference

但是,在協程外創建ClientSession顯然不是可行的方法:

➜ python 1_async.py
1_async.py:30: UserWarning: Creating a client session outside of coroutine is a very dangerous idea
  session = aiohttp.ClientSession()
Creating a client session outside of coroutine
client_session: 
Starting 'https://python.org'
Starting 'https://twitter.com'
Starting 'https://tumblr.com'
Starting 'https://example.com'
Starting 'https://github.com'
'https://twitter.com' done
'https://example.com' done
'https://github.com' done
'https://python.org' done
'https://tumblr.com' done
1_async.py:34: RuntimeWarning: coroutine 'ClientSession.close' was never awaited
  session.close()
Unclosed client session
client_session: 
Unclosed connector
connections: ['[(, 15024.110107067)]', '[(, 15024.147785039)]', '[(, 15024.252375415)]', '[(, 15024.292646968)]', '[(, 15024.342368087)]', '[(, 15024.466971983)]', '[(, 15024.602057745)]', '[(, 15024.837045568)]']
connector:

FWIW,在我嘗試上述改變之前,這是main

async def main(url):
  async with aiohttp.ClientSession() as session:
    print(f"Starting '{url}'")
    html = await fetch(session, url)
    print(f"'{url}' done")

這樣做的正確方法是什么? 我想過將一個url列表傳遞給main,但是無法以非順序的方式使它工作。

Creating a client session outside of coroutine is a very dangerous idea ,因為當你創建它時,它被綁定到當前循環。 如果你之后更改了運行循環,它將掛起。 但如果你仔細使用它,你可以忽略它。 相關文檔

至於我,我只是忽略了這個警告。 但它也很容易克服它:

async def create_session():
    return aiohttp.ClientSession()

session = asyncio.get_event_loop().run_until_complete(create_session())

此外,您不需要顯式創建Task對象,只需執行此coroutine函數:

loop.run_until_complete(asyncio.gather(
  *(main(url, session) for url in urls)
))

最后,別忘了close是一個協程。 您應該使用loop.run_until_complete(session.close())來關閉session

順便說一句,如果你想創建一個類似異步的循環,你可以參考我的另一個答案

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM