具有异步 I/O 的 Python 循环依赖

标签 python python-3.x client-server python-asyncio

在查看 Python 3.x 中的新功能时,我对添加的 asyncio 库很感兴趣。查看引用文档后,我决定尝试一下。

这一直运行良好,直到我尝试使其适用于多个客户端,并保留所有事件/连接的客户端的列表。这在服务器类和 session 类之间引入了循环依赖关系。

现在,我尝试了几种不同的方法来解决这个问题;但是,我似乎没有任何方法可以通过任何方法/功能调用直接从服务器类获取这些数据。

虽然我已经能够通过使用“惰性”导入来解决这个问题,但这似乎表明要么是设计不佳,要么是对库本身缺乏了解,要么是两者的结合。

就代码而言,我整理了一个小样本。我是否在这里缺少一个明显的解决方案,或者我的组织是否需要进行更改以更好地支持 asyncio 库提供的功能?

__main__.py:

from network.server import Server

def main(args=None):
    s = Server()

    try:
        s.run()
    except KeyboardInterrupt:
        pass

    s.close()

if __name__ == "__main__":
    main()

服务器.py:

import asyncio

from network.session import Session

class Server:

    sessionList = []

    def __init__(self):    
        self.handler = None

        self.loop = asyncio.get_event_loop()

        self.coro = self.loop.create_server(Session, 'localhost', 1234)

    def run(self):
        self.handler = self.loop.run_until_complete(self.coro)

        print('Server Running On: {}'.format(self.handler.sockets[0].getsockname()))

        self.loop.run_forever()

    def close(self):
        self.handler.close()

        self.loop.run_until_complete(self.handler.wait_closed())

        self.loop.close()

    @staticmethod
    def add_session(session):
        Server.sessionList.append(session)

    @staticmethod
    def del_session(session):
        Server.sessionList.remove(session)

session .py:

import asyncio

class Session(asyncio.Protocol):

    def __init__(self):
        from network.server import Server

        self._transport = None

        Server.add_session(self)

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

        self._transport.write('Echo Server Example\r\n\r\n'.encode())

    def data_received(self, data):
        self._transport.write(data)

    def eof_received(self):
        self._transport.close()

    def connection_lost(self, exc):
        from network.server import Server

        Server.del_session(self)

        if exc is not None:
            self._transport.close()

最佳答案

您可以将 server 实例传递给 Session 构造函数:

self.loop.create_server(lambda: Session(self), 'localhost', 1234)

sessionList 存储为全局对象并不是最佳实践。

我建议将其保存为 Server.__init__ 中的 self.sessionList = [] 并同时转换 add_sessiondel_sessionstaticmethod 转换为常规方法。

关于具有异步 I/O 的 Python 循环依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33339614/

相关文章:

java - 服务器向客户端发送消息

c++ - 从已经关闭的套接字接收数据?

sockets - 一端的套接字上的 close() 是否也会在另一端关闭?

Python 列表中浮点的成员资格

python - 将字符串打印为 HTML

python - 如何判断服务器断线(以太网线被切断的情况)

python - 将numpy矩阵转换为嵌套字典的有效方法

python - 如何使用 Python 在 Linux 中获取总运行进程数和线程数?

python - 如何下载使用 django-filebrowser 上传的文件?

python - 为什么 Python 3 中的 `input` 抛出 NameError : name. .. 未定义