简体   繁体   English

如何为asyncio创建自定义传输?

[英]How to create custom transport for asyncio?

I'm reading the documentation for Protocol and Transport classes in asyncio package. 我正在阅读asyncio包中的ProtocolTransport类的文档。 Specifically: 特别:

When subclassing a protocol class, it is recommended you override certain methods. 子类化协议类时,建议您覆盖某些方法。 Those methods are callbacks: they will be called by the transport on certain events (for example when some data is received); 这些方法是回调:它们将由传输在某些事件上调用(例如,当收到某些数据时); you shouldn't call them yourself, unless you are implementing a transport. 你不应该自己打电话, 除非你正在实施运输。

Emphasis added 强调补充说

So, in principle, it should be possible to implement a transport, but... 因此,原则上应该可以实现运输,但......

Transports are classes provided by asyncio in order to abstract various kinds of communication channels. 传输是asyncio提供的类,用于抽象各种通信信道。 You generally won't instantiate a transport yourself; 您通常不会自己实例化运输; instead, you will call an AbstractEventLoop method (which one?) which will create the transport and try to initiate the underlying communication channel, calling you back when it succeeds. 相反,您将调用一个AbstractEventLoop方法 (哪一个?) ,它将创建传输并尝试启动底层通信通道,并在成功时回拨您。

Again, emphasis added 再次强调了重点

Reading the section on AbstractEventLoop along and across I don't see any way of creating a custom transport. 阅读关于AbstractEventLoop的部分,我没有看到任何创建自定义传输的方法。 The closest it comes is in AbstractEventLoop.create_connection(protocol_factory, host=...) which only implies that it will create some kind of socket... 它最接近的是AbstractEventLoop.create_connection(protocol_factory, host=...) ,它只暗示它会创建某种套接字......

Well, my ultimate goal is to use a custom transport which isn't any kind of socket (perhaps a StringIO , perhaps a database connection cursor, perhaps another protocol). 好吧,我的最终目标是使用自定义传输,它不是任何类型的套接字(可能是StringIO ,也许是数据库连接游标,也许是另一种协议)。


So, is this just a well-intended but never implemented mistake in documentation, or is there actually a way to implement custom transport without monkey-patching asyncio and sacrificing firstborns? 那么,这只是一个很好的但是从未在文档中实现的错误,或者实际上有一种方法来实现自定义传输而不需要修补asyncio并牺牲第一个生命asyncio

A bit of boiler-plate code is needed, although it's not too much: 需要一些样板代码,尽管它不是太多:

from asyncio import streams, transports, get_event_loop


class CustomTransport(transports.Transport):

    def __init__(self, loop, protocol, *args, **kwargs):
        self._loop = loop
        self._protocol = protocol

    def get_protocol(self):
        return self._protocol

    def set_protocol(self, protocol):
        return self._protocol

    # Implement read/write methods

    # [...]


async def custom_create_connection(protocol_factory, *args, **kwargs):
    loop = get_event_loop()
    protocol = protocol_factory()
    transport = CustomTransport(loop, protocol, *args, **kwargs)
    return transport, protocol


async def custom_open_connection(*args, **kwargs):
    reader = streams.StreamReader()
    protocol = streams.StreamReaderProtocol(reader)
    factory = lambda: protocol
    transport, _ = await custom_create_connection(factory, *args, **kwargs)
    writer = streams.StreamWriter(transport, protocol, reader)
    return reader, writer

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM