Discord Bot与Quart仪表板IPC通信异常问题求助
Discord Bot + Quart 仪表板的IPC问题解决方案
一、bot.py 的事件循环冲突问题
原代码
import os import discord from discord.ext import commands, ipc from dotenv import load_dotenv load_dotenv() class BotClass(commands.Bot): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.ipc = ipc.Server(self, secret_key="Hercules") async def on_ready(self): """Called upon the bot is ready to use""" await self.ipc.start() # There were some issues with event loop, so I put the ipc.start() inside the on_ready function which fixed my issue print("Bot is ready") async def on_ipc_ready(self): """Called upon the ipc server is ready to use""" print("The ipc server is ready") async def on_ipc_error(self, endpoint, error): """Called upon the endpoint raises an error""" print(f"{error} was raised by {endpoint}") bot = BotClass(command_prefix="!", intents=discord.Intents.all()) @bot.ipc.route() async def get_guild_count(data): guild_count = len(bot.guilds) return guild_count @bot.command() async def test(ctx): await ctx.reply("Everything is working perfectly") if __name__ == "__main__": bot.run(os.getenv("BOT_TOKEN"))
错误信息
Traceback (most recent call last): File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\discord\client.py", line 377, in _run_event await coro(*args, **kwargs) File "F:\HS International\XyRic Bot Dashboard\bot.py", line 15, in on_ready await self.ipc.start() # There were some issues with event loop, so I put the ipc.start() inside the on_ready function which fixed my issue File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\discord\ext\ipc\server.py", line 262, in start self.loop.run_until_complete(self.__start(self._multicast_server, self.multicast_port)) File "E:\Python\lib\asyncio\base_events.py", line 617, in run_until_complete self._check_running() File "E:\Python\lib\asyncio\base_events.py", line 577, in _check_running raise RuntimeError('This event loop is already running') RuntimeError: This event loop is already running F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\discord\client.py:382: RuntimeWarning: coroutine 'Server.__start' was never awaited await self.on_error(event_name, *args, **kwargs) RuntimeWarning: Enable tracemalloc to get the object allocation traceback The ipc server is ready
修复方案
错误根源是ipc.start()内部调用了loop.run_until_complete(),但Discord Bot已经在运行事件循环,导致冲突。不需要用await调用start(),直接同步启动IPC服务器即可:
修改后的bot.py关键代码:
class BotClass(commands.Bot): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.ipc = ipc.Server(self, secret_key="Hercules") async def on_ready(self): print("Bot is ready") # ... 其他代码不变 if __name__ == "__main__": bot.ipc.start() # 同步启动,无需await bot.run(os.getenv("BOT_TOKEN"))
如果一定要在on_ready中启动,直接调用self.ipc.start()即可,不要加await:
async def on_ready(self): self.ipc.start() print("Bot is ready")
二、webserver.py 的IPC连接失败问题
原代码
from quart import Quart, redirect, url_for from quart_discord import DiscordOAuth2Session, requires_authorization, Unauthorized from discord.ext import ipc import os from dotenv import load_dotenv load_dotenv() app = Quart(__name__) app.secret_key = "Hercules" ipc_client = ipc.Client(secret_key="Hercules") app.config["DISCORD_CLIENT_ID"] = os.getenv("CLIENT_ID") app.config["DISCORD_CLIENT_SECRET"] = os.getenv("CLIENT_SECRET") app.config["DISCORD_REDIRECT_URI"] = "http://127.0.0.1:5000/callback" app.config["DISCORD_BOT_TOKEN"] = os.getenv("BOT_TOKEN") discord = DiscordOAuth2Session(app) @app.route("/") async def index(): guild_count = await ipc_client.request("get_guild_count") return str(guild_count) @app.route("/login/") async def login(): return await discord.create_session() @app.route("/callback/") async def callback(): try: await discord.callback() except: return redirect(url_for("login")) return redirect(url_for("select_server")) @app.route("/select_server/") async def select_server(): user = await discord.fetch_user() return f"{user.name}" if __name__ == "__main__": app.run()
错误信息
Traceback (most recent call last): File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\aiohttp\connector.py", line 980, in _wrap_create_connection return await self._loop.create_connection(*args, **kwargs) # type: ignore[return-value] # noqa File "E:\Python\lib\asyncio\base_events.py", line 1055, in create_connection raise exceptions[0] File "E:\Python\lib\asyncio\base_events.py", line 1040, in create_connection sock = await self._connect_sock( File "E:\Python\lib\asyncio\base_events.py", line 954, in _connect_sock await self.sock_connect(sock, address) File "E:\Python\lib\asyncio\proactor_events.py", line 704, in sock_connect return await self._proactor.connect(sock, address) File "E:\Python\lib\asyncio\windows_events.py", line 812, in _poll value = callback(transferred, key, ov) File "E:\Python\lib\asyncio\windows_events.py", line 599, in finish_connect ov.getresult() ConnectionRefusedError: [WinError 1225] The remote computer refused the network connection The above exception was the direct cause of the following exception: Traceback (most recent call last): File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\quart\app.py", line 1629, in handle_request return await self.full_dispatch_request(request_context) File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\quart\app.py", line 1654, in full_dispatch_request result = await self.handle_user_exception(error) File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\quart\app.py", line 1099, in handle_user_exception raise error File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\quart\app.py", line 1652, in full_dispatch_request result = await self.dispatch_request(request_context) File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\quart\app.py", line 1697, in dispatch_request return await self.ensure_async(handler)(**request_.view_args) File "F:\HS International\XyRic Bot Dashboard\webserver.py", line 21, in index guild_count = await ipc_client.request("get_guild_count") File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\discord\ext\ipc\client.py", line 97, in request await self.init_sock() File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\discord\ext\ipc\client.py", line 61, in init_sock self.multicast = await self.session.ws_connect(self.url, autoping=False) File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\aiohttp\client.py", line 779, in _ws_connect resp = await self.request( File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\aiohttp\client.py", line 536, in _request conn = await self._connector.connect( File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\aiohttp\connector.py", line 540, in connect proto = await self._create_connection(req, traces, timeout) File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\aiohttp\connector.py", line 901, in _create_connection _, proto = await self._create_direct_connection(req, traces, timeout) File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\aiohttp\connector.py", line 1206, in _create_direct_connection raise last_exc File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\aiohttp\connector.py", line 1175, in _create_direct_connection transp, proto = await self._wrap_create_connection( File "F:\HS International\XyRic Bot Dashboard\venv\lib\site-packages\aiohttp\connector.py", line 988, in _wrap_create_connection raise client_error(req.connection_key, exc) from exc aiohttp.client_exceptions.ClientConnectorError: Cannot connect to host localhost:20000 ssl:default [The remote computer refused the network connection] [2022-10-07 21:11:08 +0600] [7028] [INFO] 127.0.0.1:50415 GET /login 1.1 308 243 998
修复方案
这个错误是因为Bot的IPC服务器未正常启动(对应bot.py的事件循环问题),导致Web服务器无法连接到IPC端口。修复完bot.py后,还需注意以下两点:
- 显式指定IPC客户端的地址和端口,避免默认值不一致:
ipc_client = ipc.Client(secret_key="Hercules", host="localhost", port=20000)
- 启动顺序:先启动Bot,确认IPC服务器正常运行后,再启动Web服务器。
内容的提问来源于stack exchange,提问作者Araf
相关产品推荐
相关产品推荐

