Python 异步循环依赖 I/O
Python Cyclic Dependency with Async I/O
在查看 Python 3.x 中的新功能时,我对添加的 asyncio 库很感兴趣。在查看了参考文档后,我决定稍微尝试一下。
在我尝试让它适用于多个客户端并保留所有 active/connected 客户端的列表之前,它一直运行良好。这在服务器 class 和会话 class.
之间引入了循环依赖
现在,我尝试了几种不同的方法来解决这个问题;但是,我似乎无法通过任何 method/functional 调用直接从服务器 class 获取此数据。
虽然我已经能够通过使用 "lazy" 导入来解决这个问题,但这似乎表明我的设计不佳,对库本身缺乏了解,或者两者兼而有之.
代码明智,我有一个小样本放在一起。我在这里是否遗漏了一个明显的解决方案,或者我的组织是否需要进行更改以更好地支持 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()
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()
您可以将 server
实例传递给 Session
构造函数:
self.loop.create_server(lambda: Session(self), 'localhost', 1234)
将 sessionList
存储为全局对象不是最佳做法。
我建议在 Server.__init__
中将其保存为 self.sessionList = []
并将 add_session
和 del_session
从 staticmethod
转换为常规方法。
在查看 Python 3.x 中的新功能时,我对添加的 asyncio 库很感兴趣。在查看了参考文档后,我决定稍微尝试一下。
在我尝试让它适用于多个客户端并保留所有 active/connected 客户端的列表之前,它一直运行良好。这在服务器 class 和会话 class.
之间引入了循环依赖现在,我尝试了几种不同的方法来解决这个问题;但是,我似乎无法通过任何 method/functional 调用直接从服务器 class 获取此数据。
虽然我已经能够通过使用 "lazy" 导入来解决这个问题,但这似乎表明我的设计不佳,对库本身缺乏了解,或者两者兼而有之.
代码明智,我有一个小样本放在一起。我在这里是否遗漏了一个明显的解决方案,或者我的组织是否需要进行更改以更好地支持 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()
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()
您可以将 server
实例传递给 Session
构造函数:
self.loop.create_server(lambda: Session(self), 'localhost', 1234)
将 sessionList
存储为全局对象不是最佳做法。
我建议在 Server.__init__
中将其保存为 self.sessionList = []
并将 add_session
和 del_session
从 staticmethod
转换为常规方法。