当前位置: 首页 > 知识库问答 >
问题:

如何使 discord.py 机器人永久运行,如果客户端.run() 返回

彭宜人
2023-03-14

问题

我的discord.py机器人的client.run()每隔几天左右就会意外返回,然后出现错误“任务已被销毁,但它正在等待处理!”。

问题

为什么是客户。run()返回了吗?我怎样才能改变我的机器人来正确处理这个问题并永远运行?

代码(剥离了很多以保持讨论的简单性):

import asyncio
import discord

TOKEN = 'my bot token goes here'
CHANNEL_ID = 'my channel id goes here'

async def DiscordMsgSendTask():

  await client.wait_until_ready()
  my_channel = discord.Object(id=CHANNEL_ID)

  while not client.is_closed:

    # wait a bit to prevent busy loop
    await asyncio.sleep(2)

    # check for and handle new event here

    # if an event was handled then send a message to the channel
    embed = discord.Embed(description='Event was handled')
    await client.send_message(my_channel, embed=embed)

client = discord.Client()

while True:
  client.loop.create_task(DiscordMsgSendTask())

  try:
    client.run(TOKEN)
  except Exception as e:
    logging.warning('Exception: ' + str(e))

  client = discord.Client()

附加信息

机器人的目的基本上只是检查特定目录中的新文件,然后向特定的不和谐渠道发送消息进行报告。这一天只发生10次左右,因此机器人的流量极低。

为了让机器人容忍错误/断开,我把它放到了while True循环中,这可能是错误的方法。

使用Python 3.6.5和Discord。第0.16.12页

编辑-添加追溯

添加对当天早些时候发生的前一次故障的追溯。

2018-06-20 04:33:08 [ERROR] Task exception was never retrieved
future: <Task finished coro=<WebSocketCommonProtocol.run() done, defined at /usr/local/lib64/python3.6/site-packages/websockets/protocol.py:428> exception=ConnectionResetError(104, 'Connection reset by peer')>
Traceback (most recent call last):
  File "/usr/local/lib64/python3.6/site-packages/websockets/protocol.py", line 434, in run
    msg = yield from self.read_message()
  File "/usr/local/lib64/python3.6/site-packages/websockets/protocol.py", line 456, in read_message
    frame = yield from self.read_data_frame(max_size=self.max_size)
  File "/usr/local/lib64/python3.6/site-packages/websockets/protocol.py", line 511, in read_data_frame
    frame = yield from self.read_frame(max_size)
  File "/usr/local/lib64/python3.6/site-packages/websockets/protocol.py", line 546, in read_frame
    self.reader.readexactly, is_masked, max_size=max_size)
  File "/usr/local/lib64/python3.6/site-packages/websockets/framing.py", line 86, in read_frame
    data = yield from reader(2)
  File "/usr/lib64/python3.6/asyncio/streams.py", line 674, in readexactly
    yield from self._wait_for_data('readexactly')
  File "/usr/lib64/python3.6/asyncio/streams.py", line 464, in _wait_for_data
    yield from self._waiter
  File "/usr/lib64/python3.6/asyncio/selector_events.py", line 723, in _read_ready
    data = self._sock.recv(self.max_size)
ConnectionResetError: [Errno 104] Connection reset by peer
2018-06-20 04:33:08 [ERROR] Task was destroyed but it is pending!
task: <Task pending coro=<DiscordMsgSendTask() running at /home/bot.py:119> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x7fc99bfd7a68>()]>>
2018-06-20 04:33:08 [ERROR] Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x7fc999b59240>

共有1个答案

任文乐
2023-03-14

不能使用预定义run 方法,因为它仅处理键盘中断。您需要创建一个退出策略,该策略在关闭所有任务的同时仍保持循环运行。

当bot收到消息“die”时,以下示例将引发< code>SystemExit(模拟您的意外致命错误(RST - ConnectionError错误))。< code>SystemExit将被“捕获”并重新启动您的bot。引发< code>KeyboardInterrupt后,bot将成功退出,不会出现错误。

import asyncio
import discord

TOKEN = 'TOKEN_HERE'
client = discord.Client()


async def task():
    await client.wait_until_ready()
    while True:
        await asyncio.sleep(1)
        print('Running')


def handle_exit():
    print("Handling")
    client.loop.run_until_complete(client.logout())
    # For python 3.9, use asyncio.all_tasks instead
    for t in asyncio.Task.all_tasks(loop=client.loop):
        if t.done():
            t.exception()
            continue
        t.cancel()
        try:
            client.loop.run_until_complete(asyncio.wait_for(t, 5, loop=client.loop))
            t.exception()
        except (asyncio.InvalidStateError, asyncio.TimeoutError, asyncio.CancelledError):
            pass


while True:
    @client.event
    async def on_message(m):
        if m.content == 'die':
            print("Terminating")
            raise SystemExit

    client.loop.create_task(task())
    try:
        client.loop.run_until_complete(client.start(TOKEN))
    except SystemExit:
        handle_exit()
    except KeyboardInterrupt:
        handle_exit()
        client.loop.close()
        print("Program ended")
        break
    
    print("Bot restarting")
    client = discord.Client(loop=client.loop)

在不和谐中(有人键入die):

die

在终端(标准输出):

Running
Running
Running
Terminating
Handling
Bot restarting
Running
Running
Running
Running
Running
<CTRL-C> (KeyboardInterrupt)
Handling
Program ended

旁注:

如果您仍然对自己的错误感到困惑,那么不应该怪您的代码。Errno 104是一个服务器端致命错误,最终用户通常无法避免。

 类似资料:
  • 问题内容: 在Debian服务器上,我安装了Node.js。我了解如何使用以下命令行从腻子启动应用程序: 并通过地址(IP和端口)访问它。 但是,一旦我关闭腻子,那我就无法到达地址了。 如何使Node.js应用程序永久运行? 如您所料,我是Linux和Node.js的初学者。 问题答案: 尽管其他答案解决了OP的问题,但它们都是过大的,不能解释为什么他或她遇到此问题。 关键是这一行,“我关闭油灰,

  • 如何在IDE之外运行?虽然似乎可以使用从CLI运行独立的JNDI查找应用程序,但它似乎不适用于ACC客户端。然而,这应该是可能的: 运行应用程序客户端 使用appclient脚本运行应用程序客户端,无论是否启用Java Web Start,都可以使用appclient脚本启动ACC。 GlassFish Server开源版应用程序开发指南4.0版开发Java客户端10-15页186 步骤: 1.)

  • 我正在学习如何使用python创建一个discord bot,但我在使用这个命令时遇到了问题。我试图做的是踢一个特定的用户,然后使用bot将邀请发送回discord服务器。这是一个愚蠢的想法,但我真的想让它发挥作用。 我特别遇到的问题是如何踢一个特定的用户(带有用户标识),然后将该用户DM。 谢谢! 这里的代码: 这样做的目的是,如果具有适当角色类型的人一个特定的不一致用户id()被踢,机器人会自

  • 我试图用Python制作一个不和谐机器人,根据你所在的班级(在我的学校),给你一个不和谐服务器上的角色。我刚刚开始,但每当我试图运行它时,我都会收到一个错误(我在Python 3笔记本电脑中的Google Colab中运行它)。这是我的代码: 当我运行它时,它会显示以下错误: 如果我把命令,程序永远不会到达它,因为循环阻止它到达命令。 我错过什么了吗?我不知道问题出在哪里。非常感谢您的帮助。

  • 我有一个关于不和的问题。皮耶。我运行我的bot所在的两个独立服务器:测试服务器和主服务器。问题是,当我在测试服务器中发送消息时,bot会将其消息发送到主服务器,而不会将其发送回调用命令的服务器(仅在函数中)。 例如: 如果我在测试服务器中键入上述内容,我的bot将以“你好!”在测试服务器中。但是,如果我尝试将此代码放入函数并调用它: 通道ID显然设置为特定服务器。因此,假设我将ID“1234”作为

  • 我使用使用SSL的安全通道通过JMS与Weblogic IBM Webpsphere MQ建立了连接。我在Weblogic上的应用程序收到了来自MQ的消息。正在将应答发送到应答队列。响应头存在MQMD,它填充java。在参数持久化JMS发送值“1”中。其他系统需要在持久化时接收值“0”。如何将此参数设置为java?我猜这个参数是javax。jms。deliverymode。但我不知道怎么设置。 无