Discord机器人重启命令失效问题求助(PyCharm+异步环境)
Discord机器人重启命令失效及异步任务终止错误
我正在开发一款Discord机器人,想通过命令实现重启功能。在主脚本的客户端事件(比如error、onmessage)下方写了如下reboot命令:
@_client.command(name='reboot') async def reboot(command_context: commands.Context): # ~调试与用户验证的无关代码 os.execv(sys.executable, ['py']+sys.argv
在Discord聊天里调用这个命令后,程序以退出码0终止,但没有重启。试过相关方案都没用,怀疑是异步特性或者PyCharm的venv环境导致的问题。另外,用exit()终止程序时会出现大量异步任务相关错误:
Exception in thread Thread-16: Traceback (most recent call last): File "C:\Users\lkapp\AppData\Local\Programs\Python\Python310\lib\threading.py", line 1016, in _bootstrap_inner self.run() File "C:\Users\lkapp\AppData\Local\Programs\Python\Python310\lib\threading.py", line 1378, in run self.function(*self.args, **self.kwargs) File "C:\Users\lkapp\PycharmProjects\Imouto\cog_rcon.py", line 64, in <lambda> asyncio.run_coroutine_threadsafe( File "C:\Users\lkapp\AppData\Local\Programs\Python\Python310\lib\asyncio\tasks.py", line 885, in run_coroutine_threadsafe loop.call_soon_threadsafe(callback) AttributeError: '_MissingSentinel' object has no attribute 'call_soon_threadsafe' C:\Users\lkapp\AppData\Local\Programs\Python\Python310\lib\threading.py:1018: RuntimeWarning: coroutine 'Server_Bridge.update_player_count_in_discord_activity' was never awaited self._invoke_excepthook(self) RuntimeWarning: Enable tracemalloc to get the object allocation traceback Task was destroyed but it is pending! task: <Task pending name='Task-1' coro=<ARC.listenForData() running at C:\Users\lkapp\PycharmProjects\Imouto\bec_rcon.py:518>> Task was destroyed but it is pending! task: <Task pending name='Task-2' coro=<ARC.keepAliveLoop() running at C:\Users\lkapp\PycharmProjects\Imouto\bec_rcon.py:554>> sys:1: RuntimeWarning: coroutine 'ARC.listenForData' was never awaited RuntimeWarning: Enable tracemalloc to get the object allocation traceback C:\Users\lkapp\AppData\Local\Programs\Python\Python310\lib\asyncio\base_events.py:671: RuntimeWarning: coroutine 'ARC.keepAliveLoop' was never awaited self._ready.clear() RuntimeWarning: Enable tracemalloc to get the object allocation traceback Task exception was never retrieved future: <Task finished name='discord.py: on_message' coro=<Client._run_event() done, defined at C:\Users\lkapp\PycharmProjects\Imouto\venv\lib\site-packages\discord\client.py:401> exception=SystemExit()> Traceback (most recent call last): File "C:\Users\lkapp\PycharmProjects\Imouto\venv\lib\site-packages\discord\client.py", line 828, in run asyncio.run(runner()) File "C:\Users\lkapp\AppData\Local\Programs\Python\Python310\lib\asyncio\runners.py", line 44, in run return loop.run_until_complete(main) File "C:\Users\lkapp\AppData\Local\Programs\Python\Python310\lib\asyncio\base_events.py", line 633, in run_until_complete self.run_forever() File "C:\Users\lkapp\AppData\Local\Programs\Python\Python310\lib\asyncio\windows_events.py", line 321, in run_forever super().run_forever() File "C:\Users\lkapp\AppData\Local\Programs\Python\Python310\lib\asyncio\base_events.py", line 600, in run_forever self._run_once() File "C:\Users\lkapp\AppData\Local\Programs\Python\Python310\lib\asyncio\base_events.py", line 1896, in _run_once handle._run() File "C:\Users\lkapp\AppData\Local\Programs\Python\Python310\lib\asyncio\events.py", line 80, in _run self._context.run(self._callback, *self._args) File "C:\Users\lkapp\PycharmProjects\Imouto\venv\lib\site-packages\discord\client.py", line 409, in _run_event await coro(*args, **kwargs) File "C:\Users\lkapp\PycharmProjects\Imouto\main.py", line 43, in on_message await _client.process_commands(message) File "C:\Users\lkapp\PycharmProjects\Imouto\venv\lib\site-packages\discord\ext\commands\bot.py", line 1389, in process_commands await self.invoke(ctx) # type: ignore File "C:\Users\lkapp\PycharmProjects\Imouto\venv\lib\site-packages\discord\ext\commands\bot.py", line 1347, in invoke await ctx.command.invoke(ctx) File "C:\Users\lkapp\PycharmProjects\Imouto\venv\lib\site-packages\discord\ext\commands\core.py", line 986, in invoke await injected(*ctx.args, **ctx.kwargs) # type: ignore File "C:\Users\lkapp\PycharmProjects\Imouto\venv\lib\site-packages\discord\ext\commands\core.py", line 190, in wrapped ret = await coro(*args, **kwargs) File "C:\Users\lkapp\PycharmProjects\Imouto\cog_rcon.py", line 268, in debug sys.exit() SystemExit Task was destroyed but it is pending! task: <Task pending name='Task-150' coro=<Server_Bridge.cycle_reconnect() done, defined at C:\Users\lkapp\PycharmProjects\Imouto\cog_rcon.py:169> wait_for=<Future pending cb=[Task.task_wakeup()]> cb=[_chain_future.<locals>._call_set_state() at C:\Users\lkapp\AppData\Local\Programs\Python\Python310\lib\asyncio\futures.py:392]> Process finished with exit code 0
解决方法
1. 修复os.execv的参数与语法错误
你的代码有两个明显问题:
- 末尾缺少闭合括号,属于语法错误
['py']参数冗余,sys.executable已经指向当前运行的Python解释器完整路径,直接用[sys.executable] + sys.argv即可,避免依赖Windows的py启动器
修正后的重启命令:
import os import sys from discord.ext import commands @_client.command(name='reboot') async def reboot(command_context: commands.Context): # 用户验证逻辑 await command_context.send("正在重启机器人...") # 先优雅关闭客户端,清理Discord相关异步资源 await _client.close() # 重启进程 os.execv(sys.executable, [sys.executable] + sys.argv)
2. 优雅终止自定义异步任务
直接重启会导致未完成的异步任务被强制销毁,引发警告。如果有自定义异步任务(比如ARC.listenForData、Server_Bridge.cycle_reconnect),需要手动取消并等待任务结束:
# 初始化时保存任务引用 listen_task = None keep_alive_task = None async def start_custom_tasks(): global listen_task, keep_alive_task listen_task = asyncio.create_task(ARC.listenForData()) keep_alive_task = asyncio.create_task(ARC.keepAliveLoop()) @_client.command(name='reboot') async def reboot(command_context: commands.Context): await command_context.send("正在重启机器人...") # 取消自定义任务 if listen_task: listen_task.cancel() if keep_alive_task: keep_alive_task.cancel() # 等待任务处理取消信号 try: if listen_task: await listen_task if keep_alive_task: await keep_alive_task except asyncio.CancelledError: pass # 关闭客户端后重启 await _client.close() os.execv(sys.executable, [sys.executable] + sys.argv)
3. 规避PyCharm虚拟环境的干扰
PyCharm启动脚本时会添加调试相关的sys.argv参数,可能导致重启异常。可以:
- 激活venv后,用命令行直接运行
python main.py - 若需要调试,过滤掉
sys.argv中的PyCharm参数,只保留脚本本身和自定义参数
内容的提问来源于stack exchange,提问作者Lucas Kappel
相关产品推荐
相关产品推荐

