我需要用 python 进行快速实验。 但是,我遇到了异步问题。我对 python 异步编程不太熟悉,所以请耐心等待。
我想要的是运行一个脚本,在不同的端口启动不同的守护进程,然后等待与其建立连接。
我基本上使用了下面的代码(它不会运行,因为我想简化问题,但它应该足以说明问题。如果没有,请告诉我)。
我遇到的问题是这段代码(对于专家来说可能是显而易见的)在第一个
sleep_forever
处停止。换句话说,只有一个守护进程启动。
这可以通过同一个脚本完成吗?或者我是否需要子流程(或完全其他的东西)来启动? 我尝试从
await
中删除 self.__start()
,但这会导致错误提示 __start() was not awaited
。我的想法是,那么异步函数确实不会被等待,脚本将继续,而网络内容将被启动,然后它会等待。看起来好像不是这样的。我也尝试过启动任务,但是任务也需要等待?
import trio
class Daemon:
port: int
@classmethod
async def new(cls, port):
self = cls()
self.port = port
#assume this to return an `AbstractAsyncContextManager`
self.server = create_server() `
await self.__start()
async def __start(self):
print("starting with port...".format(port=self.port))
# init network socket
async with self.server.start(port=self.port), trio.open_nursery() as nursery:
#setup network objects
print("server ok")
# ->> WAIT FOR INCOMING Connections
await trio.sleep_forever()
print("exiting.")
async def run():
d_list = []
num = 3
for i in range(num):
d = await Daemon.new(5000+i)
d_list.append(d)
if __name__ == "__main__":
trio.run(run)
您编写的是一个完全没有并发性的单线程程序。它将依次创建每个守护进程并等待该守护进程完成,然后再继续循环的下一次迭代。这根本不是你想要的。
需要使用asyncio提供并发的功能。这个功能是
Task
。任务将继续执行,直到找到无法立即完成的 await
语句。例如 sleep()
或等待套接字连接。
保留对尚未完成的任务的引用至关重要。如果不这样做可能(将)意味着任务将无法完成。由于您已经在使用
trio
,请使用它的托儿所来为您处理。
在程序中使用任务是一个简单的切换。
async def run():
num = 3
async with trio.open_nursery() as nursery:
for i in range(num):
nursery.start_soon(Daemon.new, 5000+i)
print('all tasks in the nursery will have stopped after the with block')
# however, as your daemons never return, this print statement is never executed