gpt4 book ai didi

python-3.x - 在 Python 中关闭异步事件循环会导致异常结束

转载 作者:行者123 更新时间:2023-12-03 16:32:24 26 4
gpt4 key购买 nike

对于在 Windows 上的 Python 3.4 中使用 asyncio 和 aiohttp 的 https 请求,我需要使用 2 个事件循环。用于运行 shell 命令的 ProactorEventLoop,以及用于 HTTPS 请求的默认事件循环。不幸的是,ProactorEventLoop 不适用于 HTTPS 命令。

下面的代码显示了当我使用新创建的默认事件循环并尝试在 Windows 上结束时关闭它时发生的情况。如果我在最后调用 loop.close ,我会在最后得到异常,如下所示:

> Traceback (most recent call last):
> File "C:\BuildUtilities\p3.4env0\lib\site-packages\aiohttp\connector.py", line 56, in __del__
> self.close()
> File "C:\BuildUtilities\p3.4env0\lib\site-packages\aiohttp\connector.py", line 97, in close
> transport.close()
> File "C:\Python34\Lib\asyncio\selector_events.py", line 375, in close
> self._loop.remove_reader(self._sock_fd)
> File "C:\Python34\Lib\asyncio\selector_events.py", line 155, in remove_reader
> key = self._selector.get_key(fd)
> AttributeError: 'NoneType' object has no attribute 'get_key'

将其注释掉会删除异常,我不知道为什么。唯一的

import asyncio
import aiohttp

@asyncio.coroutine
def get_body(url):
response = yield from aiohttp.request('GET', url)
return (yield from response.read_and_close())

#loop = asyncio.ProactorEventLoop()
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)

f = asyncio.async( get_body('https://www.google.com') )
try:
loop.run_until_complete(f)
except Exception as e:
print(e)

if f.result():
print(f.result())

loop.close()

谢谢,格林杰

最佳答案

更新:看起来问题已在 github 版本 (0.7.2) 中修复。它不会产生错误。作为@danj.py said , 它由 "Get rid of __del__ in connector" commit 修复.


它不是 ProactorEventLoop 或 Windows 特定的。我可以使用默认事件循环在 Ubuntu 上重现错误:

#!/usr/bin/env python3
import asyncio
import aiohttp # $ pip install aiohttp

@asyncio.coroutine
def get_body(url):
response = yield from aiohttp.request('GET', url)
return (yield from response.read_and_close())

loop = asyncio.get_event_loop()
body = loop.run_until_complete(get_body('https://stackoverflow.com/q/23283502'))
print(len(body), type(body), body[:200])
loop.close()

这可能是 aiohttp 中的错误,因为用法似乎是正确的。

不加aiohttp请求不会报错:

#!/usr/bin/env python3
import asyncio
from contextlib import closing
from urllib.parse import urlsplit

@asyncio.coroutine
def get_body(url):
# parse url
url = urlsplit(url)
path = '/' * (not url.path) + url.path + '?' * bool(url.query) + url.query
# open connection
reader, writer = yield from asyncio.open_connection(
host=url.hostname,
port=url.port or (443 if url.scheme == 'https' else 80),
ssl=(url.scheme == 'https'))
with closing(writer):
# send request
writer.write(b'GET ' + path.encode('ascii') + b' HTTP/1.1\r\n'
b'Host: ' + url.netloc.encode('ascii') + b'\r\n'
b'Connection: close\r\n\r\n')
# read headers
while True:
line = yield from reader.readline()
line = line.rstrip(b'\n\r')
print(line.decode('latin-1'))
if not line:
break
# read body
body = yield from reader.read()
return body

loop = asyncio.get_event_loop()
body = loop.run_until_complete(get_body('https://stackoverflow.com/q/23283502'))
print(len(body), type(body), body[:200])
loop.close()

注意:示例并不完全等同,例如,后者不遵循重定向。

关于python-3.x - 在 Python 中关闭异步事件循环会导致异常结束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23283502/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com