Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/348.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
理解python异步IO协议_Python_Python Asyncio - Fatal编程技术网

理解python异步IO协议

理解python异步IO协议,python,python-asyncio,Python,Python Asyncio,我对Python异步IO和协议是如何工作的缺乏了解 似乎相关的文档: 状态机显示相关的转换 echo tcp客户端的示例代码: import asyncio class EchoClientProtocol(asyncio.Protocol): def __init__(self, message, loop): self.message = message.encode() def connection_made(self, transport):

我对Python异步IO和协议是如何工作的缺乏了解

似乎相关的文档:

状态机显示相关的转换

echo tcp客户端的示例代码:

import asyncio

class EchoClientProtocol(asyncio.Protocol):
    def __init__(self, message, loop):
        self.message = message.encode()

    def connection_made(self, transport):
        self.transport = transport
        self.write_data()

    def data_received(self, data):
        print('Data received: {!r}',len(data))
        self.write_data()

    def eof_received(self):
        print("eof")
        return True

    def write_data(self):
        print("write")
        self.transport.write(self.message)

    def connection_lost(self, exc):
        print('The server closed the connection')
        print('Stop the event loop')


loop = asyncio.get_event_loop()
message = 'Hello World!'

coro = loop.create_connection(lambda: EchoClientProtocol(message, loop),
                              '127.0.0.1', 5676)
loop.run_until_complete(coro)
print("done")
在echo服务器上连接时的输出:

write
Data received: {!r} 12
write
done
据我所知,这应该一直运行到连接关闭

发件人:

每次成功连接都会精确调用一次connection_Maked()和connection_lost()。所有其他回调都将在这两个方法之间调用,这使得协议实现中的资源管理更加容易

从状态机:

start 
-> connection_made
[-> data_received]*
[-> eof_received]?
-> connection_lost 
-> end
但是,永远不会调用函数
EchoClientProtocol.connection\u lost
,并且
循环。运行\u,直到\u complete(coro)
在协议完成之前终止

问题是:

如何获取封装协议的协程/未来,使其在达到协议的结束状态时完成,并循环。运行直到在此类事件中返回“完成”。

循环。运行直到完成(coro)
返回
传输,协议

因此,要触发连接丢失,服务器或客户端都应该关闭连接。因此,您需要:

transport, _ = loop.run_until_complete(coro)
transport.close()
loop.run_forever()
print("done")
由于您没有停止
连接\u lost
中的循环,因此它将在此处永远被阻止


顺便说一句,
coro
在连接成功时返回。

正如Sraw的回答所指出的,
loop.create\u connection
是一个在创建传输/协议对后立即返回的协程。因此,您需要运行另一个协同程序(或等效对象),以使事件循环保持活动状态,以便发生有趣的事情

如何运行循环,直到协议内部状态达到状态结束,而不显式关闭循环

您不一定需要关闭或停止循环。如果我没记错的话,您可能希望避免一次难看的
永远运行
,而不是编写以下内容:

transport, protocol = loop.run_until_complete(coro)
transport.close()
loop.run_until_complete(protocol.wait_connection_lost())
虽然asyncio确实没有提供
wait\u connection\u lost()
,但您提供了协议实现,因此您可以轻松地为您的协议创建一个:

class EchoClientProtocol(asyncio.Protocol):
    # your other methods are unchanged

    def __init__(self, message, loop):
        self.message = message.encode()
        self.__done = loop.create_future()

    def connection_lost(self, exc):
        # the value passed to set_result will be transmitted to
        # run_until_complete(protocol.wait_connection_lost()).
        self.__done.set_result(None)

    # When awaited, resumes execution after connection_lost()
    # has been invoked on this protocol.
    def wait_connection_lost(self):
        return self.__done

谢谢你的回答。您知道如何运行循环直到协议内部状态达到状态结束而不显式关闭循环。不,在
asyncio
中似乎没有用于此的接口。