为何Python asyncio任务未执行却报告已完成?
问题
为什么任务aioStartServerTask还没执行完核心启动逻辑就报告已完成?正常执行的话,日志里应该出现here和服务器启动的相关输出,但实际没有,而且app.aioServer始终是None,最终触发AttributeError异常。
环境:Python 3.12
相关代码:
from os import path as ospath import asyncio import socket as Socket import logger as log logger = log.getLogger(fileName=ospath.join('log', 'server.log'), initialize=True) class App(): def __init__(self) -> None: self.quit = False self.aioServer = None self.clients = [] async def clientHandler(self, reader, writer): logger.info('client handler starting') async def aioServerStart(self): logger.info('aioServerStart') async def startServer(x=self): logger.info('here') ipaddr = Socket.gethostbyname(Socket.gethostname()) port = 32843 logger.info(f'starting socket server ({ipaddr}:{port})') x.aioServer = await asyncio.start_server(self.clientHandler, ipaddr, port=32843) return startServer async def main(): logger.info("server app starting") app = App() aioStartServerTask = asyncio.create_task(app.aioServerStart()) logger.info(f'task done: {aioStartServerTask.done()}') logger.info('waiting for server to start...') await aioStartServerTask while not aioStartServerTask.done(): await asyncio.sleep(.5) logger.info('waiting...') logger.info(f'task done: {aioStartServerTask.done()}') await asyncio.sleep(2) await aioStartServerTask logger.info('closing server') app.aioServer.close() await app.aioServer.wait_closed() logger.info('server closed') if __name__ == '__main__': asyncio.run(main())
运行输出:
$ python server.py INFO - 2024-09-29 19:42:49,861 - root - initialized logger - None INFO - 2024-09-29 19:42:49,861 - root - server app starting INFO - 2024-09-29 19:42:49,861 - root - task done: False INFO - 2024-09-29 19:42:49,862 - root - waiting for server to start... INFO - 2024-09-29 19:42:49,862 - root - aioServerStart INFO - 2024-09-29 19:42:49,862 - root - task done: True INFO - 2024-09-29 19:42:51,864 - root - closing server Traceback (most recent call last): File "/home/david/python/opcua/server.py", line 79, in <module> asyncio.run(main()) File "/usr/lib/python3.12/asyncio/runners.py", line 194, in run return runner.run(main) ^^^^^^^^^^^^^^^^ File "/usr/lib/python3.12/asyncio/runners.py", line 118, in run return self._loop.run_until_complete(task) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.12/asyncio/base_events.py", line 687, in run_until_complete return future.result() ^^^^^^^^^^^^^^^ File "/home/david/python/opcua/server.py", line 74, in main app.aioServer.close() ^^^^^^^^^^^^^^^^^^^ AttributeError: 'NoneType' object has no attribute 'close'
解答
问题核心是aioServerStart这个异步函数根本没执行启动服务器的逻辑:它只是定义了内部的startServer协程函数,然后直接返回了这个函数,没有调用执行它。
当你await aioStartServerTask时,任务完成的标志是aioServerStart函数执行完毕——也就是返回内部函数就算完成了,而真正负责启动服务器的startServer协程从未被运行,所以日志里没有here的输出,app.aioServer也一直是None。
修复方案
直接去掉多余的内部嵌套函数,把启动逻辑放在aioServerStart里直接执行:
async def aioServerStart(self): logger.info('aioServerStart') logger.info('here') ipaddr = Socket.gethostbyname(Socket.gethostname()) port = 32843 logger.info(f'starting socket server ({ipaddr}:{port})') self.aioServer = await asyncio.start_server(self.clientHandler, ipaddr, port=32843)
如果一定要保留内部函数的写法,需要在aioServerStart里调用并await这个内部协程:
async def aioServerStart(self): logger.info('aioServerStart') async def startServer(x=self): logger.info('here') ipaddr = Socket.gethostbyname(Socket.gethostname()) port = 32843 logger.info(f'starting socket server ({ipaddr}:{port})') x.aioServer = await asyncio.start_server(self.clientHandler, ipaddr, port=32843) await startServer() # 关键:执行并等待内部协程完成
另外main里那段while not aioStartServerTask.done()的循环是多余的——await本身就会等待任务完成才继续执行,这段循环永远不会被触发。
修复后,app.aioServer会被正确初始化,日志会出现预期输出,关闭服务器的代码也能正常执行。
内容的提问来源于stack exchange,提问作者iamthebull
相关产品推荐
相关产品推荐

