使用异步I / O的Python循环依赖

时间:2015-10-26 06:23:00

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

在查看Python 3.x中的新功能时,我对添加的asyncio库很感兴趣。在查看参考文档后,我决定稍微使用它。

这很有效,直到我尝试使其适用于多个客户端,并保留所有活动/连接客户端的列表。这引入了服务器类和会话类之间的循环依赖。

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

虽然我已经能够通过使用" lazy"来解决这个问题。导入,看起来这似乎表明设计不佳,对图书馆本身缺乏了解,或两者兼而有之。

代码方面,我有一个小样本放在一起。我在这里错过了一个明显的解决方案,还是我的组织需要更改以更好地支持asyncio库提供的功能?

__主__ PY:

from network.server import Server

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

    try:
        s.run()
    except KeyboardInterrupt:
        pass

    s.close()

if __name__ == "__main__":
    main()

server.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()

1 个答案:

答案 0 :(得分:2)

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

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

sessionList存储为全局对象不是最佳做法。

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