You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 06:30:51