EventLoop.sock_accept() 的优雅中断

Graceful interrupt of EventLoop.sock_accept()

考虑下面的代码,如何在listen()中停止执行?它似乎在 sock.close() 被调用后挂起。没有出现异常

#!/usr/bin/env python3.5

import asyncio, socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('localhost', 8080))
sock.listen()
sock.setblocking(0)

async def listen():
    print('listen')
    try:
        while True:
            await asyncio.get_event_loop().sock_accept(sock)
            print('accepted')
    except:
        print('exc')

async def stop():
    await asyncio.sleep(1)
    sock.close()
    print('stopped')


asyncio.ensure_future(listen())
asyncio.ensure_future(stop())
asyncio.get_event_loop().run_forever()

使用loop.remove_reader does not notify loop.sock_accept关闭套接字或删除文件描述符。

要么明确取消:

# Listening
accept_future = asyncio.ensure_future(loop.sock_accept(sock))
await accept_future
[...]
# Closing
loop.remove_reader(sock.fileno())
sock.close()
accept_future.cancel()

或者使用更高级的协程,例如loop.create_server or asyncio.start_server:

# Using a protocol factory
server = await loop.create_server(protocol_factory, sock=sock) 
# Using callback and streams
server = await asyncio.start_server(callback, sock=sock)