Python 3.x 在Python中关闭asyncio事件循环会导致结束时出现异常

Python 3.x 在Python中关闭asyncio事件循环会导致结束时出现异常,python-3.x,python-asyncio,aiohttp,Python 3.x,Python Asyncio,Aiohttp,对于在Windows上使用Python 3.4中的asyncio和aiohttp的https请求,我需要使用2个事件循环。用于运行shell命令的ProactReventLoop,以及用于HTTPS请求的默认事件循环。不幸的是,ProactorEventLoop不适用于HTTPS命令 下面的代码显示了当我使用新创建的默认事件循环并尝试在Windows上结束时关闭它时会发生什么。如果我调用循环,我会在末尾得到异常。在末尾关闭,如下所示: > Traceback (most recent ca

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

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

> 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()
谢谢,
greenaj

更新:这个问题似乎在github版本(0.7.2)中得到了解决。它不会产生错误。如图所示,它由


它不是特定于ProactReventLoop或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中的一个bug,因为用法似乎正确

如果在没有
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()

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

J.F.Sebastian认为这是aiohttp的错误是正确的

看起来此问题已通过以下提交解决

在撰写本文时,这似乎还没有进入pypi。

实际上,这是Python 3.4本身的一个(修复的)错误:

作为临时解决方案(为了支持Python 3.3),我提出了pull请求


但是,再说一遍,问题的根源是Python3.4.0中的垃圾收集器(由即将发布的Python3.4.1错误修复版本修复)。

您是正确的。我无法重现以
a229110
commit开头的错误。我已验证在64位Windows 7中关闭SelectorEventLoop不再崩溃。A
pip安装aiohttp——升级
解决了问题,将aiohttp从0.7.0升级到0.7.2。非常感谢。