Requests
: вам не нужно явно звонить close()
. запрос будет автоматически закрыт после завершения, потому что он основан на urlopen (вот почему resp.raw.closed
имеет значение True). Это упрощенный код после того, как я посмотрел session.py
и adapters.py
:
from urllib3 import PoolManager
import time
manager = PoolManager(10)
conn = manager.connection_from_host('host1.example.com')
conn2 = manager.connection_from_host('host2.example.com')
res = conn.urlopen(url="http://host1.example.com/",method="get")
print(len(manager.pools))
manager.clear()
print(len(manager.pools))
print(res.closed)
#2
#0
#True
Тогда что же сделал __exit__
? Используется для очистки PoolManager(self.poolmanager=PoolManager(...))
и proxy
.
# session.py
def __exit__(self, *args): #line 423
self.close()
def close(self): #line 733
for v in self.adapters.values():
v.close()
# adapters.py
# v.close()
def close(self): #line 307
self.poolmanager.clear()
for proxy in self.proxy_manager.values():
proxy.clear()
Поэтому, когда вам нужно использовать close()
, как сказано в примечании Освобождает соединение обратно в пул , потому что DEFAULT_POOLSIZE = 10
(http / https независимы). Это означает, что если вы хотите получить доступ к более чем 10 веб-сайтам за один сеанс, вы можете закрыть некоторые из них, которые вам не нужны, иначе менеджер закроет соединение с первого на самый новый, когда у вас будет еще один. Но на самом деле вам не нужно заботиться об этом, вы можете указать размер пула, и это не будет тратить много времени на восстановление соединения
aiohttp
aiohttp.ClientSession () использует один TCPConnector для всех запросов. Когда сработает __aexit__
, self._connector
будет закрыт.
Редактировать: s.request()
настроил соединение с хоста, но он не получил ответа. await resp.text()
можно сделать только после получения ответа, если вы не сделали такой шаг (дождитесь ответа), вы выйдете без ответа.
if connector is None: #line 132
connector = TCPConnector(loop=loop)
...
self._connector = connector #line 151
# connection timeout
try:
with CeilTimeout(real_timeout.connect,loop=self._loop):
assert self._connector is not None
conn = await self._connector.connect(
req,
traces=traces,
timeout=real_timeout
)
...
async def close(self) -> None:
if not self.closed:
if self._connector is not None and self._connector_owner:
self._connector.close()
self._connector = None
...
async def __aexit__(self,
...) -> None:
await self.close()
Это код, чтобы показать, что я сказал
import asyncio
import aiohttp
import time
async def get():
async with aiohttp.ClientSession() as s:
# The response is already closed after this `with` block.
# Why would it need to be used as a context manager?
resp = await s.request('GET', 'https://www.stackoverflow.com')
resp2 = await s.request('GET', 'https://www.github.com')
print("resp:",resp._closed)
print("resp:",resp._connection)
print("resp2:",resp2._closed)
print("resp2:",resp2._connection)
s.close()
print(s.closed)
c = await resp.text()
d = await resp2.text()
print()
print(s._connector)
print("resp:",resp._closed)
print("resp:",resp._connection)
print("resp2:",resp2._closed)
print("resp2:",resp2._connection)
loop = asyncio.get_event_loop()
loop.run_until_complete(get()) # Python 3.5 +
#dead loop