Python asyncio / aiohttp:有关BaseProtocol.connection_lost()的要求是什么?

时间:2017-05-24 09:40:38

标签: python python-3.x python-asyncio aiohttp

connection_lost状态的py documentation

  每次成功连接时,都会调用

connection_made()和connection_lost()。

还有下面的状态机:

  

开始 - > connection_made()[ - > data_received()*] [ - > eof_received()?] - > connection_lost() - >端

此外,BaseTransport.close()的{​​{3}}州:

  

刷新所有缓冲数据后,将调用协议的connection_lost()方法,并将None作为参数。

以及WriteTransport.abort()州的documentation

  

最终将使用None作为参数调用协议的connection_lost()方法。

在我看来,这表明了以下责任:

  1. 传输必须,如果它已调用connection_made(),稍后还会在协议上调用connection_lost()(无论是否因为调用{{}而导致连接丢失1}},对close()的调用或基础连接的问题。
  2. abort()close()的调用返回时,协议不得假设I / O已完成。它必须等待abort()的呼叫。特别是,在connection_lost()close()返回后,可能会有与仍在事件循环中安排的传输相关的工作。
  3. 考虑到这一点,请考虑以下简单的aiohttp客户端程序,使用SSL:

    abort()

    在我的(Windows)机器上运行它似乎工作 正确。但是,如果我把断点或打印语句放入 aiohttp的import aiohttp import asyncio async def main(): conn = aiohttp.TCPConnector(verify_ssl=False) async with aiohttp.ClientSession(connector=conn) as session: async with session.post('https://whatevs/') as resp: resp.raise_for_status() loop = asyncio.get_event_loop() try: loop.run_until_complete(main()) finally: loop.close() connection_made()方法 connection_lost()类(协议实现),我明白了 ResponseHandler被调用,但connection_made()不是。

    使用的传输是connection_lost(),在asyncio中定义 _SSLProtocolTransport个文件。它的sslproto.py方法调用,它就会启动 关机过程。由于SSL的性质,这个关机过程是 必然是异步的,期望似乎是一次 关闭是完成close()的基础 从SSLProtocol方法开始,_SSLProtocolTransport会关闭 底层传输。这将导致呼叫 _finalize()冒泡堆栈。但是,这一切都没有 异步的东西实际发生。 aiohttp似乎只是打电话 connection_lost并立即放弃close()( 这样做的方法甚至不是协程)和传输 从不以关机顺序进行,也从不打电话 _SSLProtocolTransport

    所以我的问题是:这是aiohttp和/或aysncio的SSL中的错误 协议/传输,或者我误解了文档 关于运输和协议的责任?

    为什么我要求

    这个问题的原因是我写了一个SSL传输 我自己,允许我使用PyOpenSSL与asyncio,而不是 标准库connection_lost()模块。在我的实现中,在调用之后 我的ssl方法返回,仍有回调排队 事件循环(使用close()计划)。这是必要的 用于正确执行异步关闭序列,以及 我希望协议给我的运输机会完成 处理并致电call_soon()

    当我使用aiohttp的传输时,使用connection_lost()方法 在上面的代码中创建的__aexit__会调用自己的ClientSession 方法(不是协程),导致我的运输被关闭, 无需等待close()。然后关闭事件循环 当运输工具仍在运行时,模块最终确定 执行I / O,导致各种错误。

    我试图弄清楚这是我的错还是aiohttp中的错误 (也许还有asyncio的SSL传输)。如果这是我的错,我需要 知道我应该如何执行这种异步关机。一世 原则上可以通过运行事件在顶层处理它 在调用loop.close()之前循环直到它为空,但我没有看到任何内容 这样做的方式(那里connection_lost(),但这不起作用 用Task.all_tasks())安排的事情。即使我能以某种方式做到这一点,它 看起来非常丑陋,肯定不会被描述为 任何此类工作后关闭的标准要求 我在asyncio或aiohttp上看过的文档。

1 个答案:

答案 0 :(得分:0)

我建议你在aiohttp bug跟踪器中创建一个问题,然后将你的问题复制到其中。 恕我直言Stack Overflow不是讨论此类问题的最佳场所。