如何在多进程中运行Asyncio任务与命令行子进程?解决属性错误
解决方案:同时运行Asyncio Steam机器人与Steam Desktop Authenticator GUI
问题根源分析
- aioprocessing报错:大概率是误用了非可等待对象(比如直接
await未正确包装的进程实例),导致出现object nonetype cannot be used in await错误。 - ProcessPoolExecutor报错:
MyClient作为SteamIO的异步客户端对象,包含事件循环、套接字等不可序列化的内部属性。ProcessPoolExecutor会对任务参数进行序列化/反序列化,子进程中重建的MyClient会丢失关键属性(如_closed),从而触发AttributeError。
正确实现思路
不需要额外的进程池库,直接利用Asyncio原生能力处理两个任务:
- Steam机器人作为Asyncio任务在主事件循环中运行。
- 用Asyncio的
create_subprocess_exec启动Wine运行SDA GUI,将子进程与事件循环集成,避免跨进程序列化问题。
代码示例
import asyncio from steamio import Client class MyClient(Client): # 实现你的Steam机器人逻辑,比如消息处理、登录回调等 async def on_ready(self): print("Steam机器人已登录") async def start_sda(): # Mac环境下启动Wine运行SDA的命令,替换为你的SDA实际路径 sda_exe_path = "/path/to/SteamDesktopAuthenticator.exe" process = await asyncio.create_subprocess_exec( "wine", sda_exe_path, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE ) # 保持SDA运行,直到手动关闭或进程退出 await process.wait() async def main(): # 初始化Steam机器人 client = MyClient() # 启动机器人任务(根据SteamIO文档传入登录凭证) client_task = asyncio.create_task(client.start(username="your_steam_user", password="your_steam_pass")) # 启动SDA任务 sda_task = asyncio.create_task(start_sda()) # 等待两个任务完成(return_exceptions=True避免单个任务崩溃导致整体退出) await asyncio.gather(client_task, sda_task, return_exceptions=True) if __name__ == "__main__": try: asyncio.run(main()) except KeyboardInterrupt: print("程序已终止")
关键注意事项
- 确保Mac上已正确安装Wine,且SDA的exe路径无误。
- Steam机器人的登录逻辑需遵循SteamIO官方文档,可能需要处理验证码、令牌等验证步骤。
- 若需监控SDA的输出日志,可通过
process.stdout.readline()循环读取;若需终止SDA,调用process.terminate()即可。 - 如需优雅退出,可添加信号监听(如
SIGINT),在触发时先关闭Steam机器人客户端,再终止SDA进程。
内容的提问来源于stack exchange,提问作者Andrew Ryan
相关产品推荐
相关产品推荐

