WinError 10038 и, может быть, плохо реализованные таймауты цикла задач? (тоже материал discord.py) Нуб при кодировании здесь

У меня чуть больше 3 недель на то, чтобы научить себя питону, так что терпите меня:')

У меня есть цикл задач, который запускается каждые 5 секунд бесконечно, пока бот работает, бот запускается из фреймворка «RED discord bot», который использует модули, называемые «винтики», над которыми я работал, вот часть моего кода у меня были проблемы с:

          # Crosschat loop logic
    @tasks.loop(seconds=5)
    async def getchat(self):
        await self.bot.wait_until_red_ready()
        data = await self.config.all_guilds()
        for guildID in data:
            guild = self.bot.get_guild(int(guildID))
            if not guild:
                continue
            guildsettings = await self.config.guild(guild).clusters()
            if not guildsettings:
                continue

            for cluster in guildsettings:
                if not guildsettings[cluster]:
                    continue
                globalchat = guildsettings[cluster]["globalchatchannel"]
                for server in guildsettings[cluster]["servers"]:
                    guildsettings[cluster]["servers"][server]["cluster"] = cluster
                    guildsettings[cluster]["servers"][server]["globalchat"] = globalchat
                    if not guildsettings[cluster]["servers"][server]["chatchannel"]:
                        return
                    channel = guild.get_channel(int(guildsettings[cluster]["servers"][server]["chatchannel"]))
                    if not channel:
                        return

                    """Loop using asyncio task loop"""
                    chattask = []
                    chattask.append(self.getchatrcon(guild,
                                                  guildsettings[cluster]["servers"][server]["cluster"],
                                                  guildsettings[cluster]["servers"][server]
                                                  ))

                    # Gathers the getchat tasks with a timeout (i think i did it right)
                    tasks = asyncio.gather(*chattask)
                    try:
                        await asyncio.wait_for(tasks, timeout=10)
                    except asyncio.TimeoutError:
                        return
    # rcon logic for sending a command to the ark servers and returning the message to their designated discord channels.
    async def getchatrcon(self, guild, cluster, server):
        guildsettings = await self.config.guild(guild).clusters()
        adminlogchannel = guild.get_channel(int(guildsettings[cluster]["adminlogchannel"]))
        globalchat = guild.get_channel(int(server["globalchat"]))
        chatchannel = guild.get_channel(int(server["chatchannel"]))

        try:
            res = await rcon.asyncio.rcon(
                command="getchat",
                host=server['ip'],
                port=server['port'],
                passwd=server['password']
            )
            if "Server received, But no response!!" in res:
                return
            msgs = res.split("\n")
            filteredmsg = []
            for msg in msgs:
                if msg.startswith("AdminCmd:"):
                    adminmsg = msg
                    await adminlogchannel.send(f"**{server['name'].capitalize()}**\n{box(adminmsg, lang='python')}")
                if "): " not in msg:
                    continue
                if "tribe" and ", ID" in msg.lower():
                    continue  # Add more features at a later date for tribe log channels
                else:
                    if msg not in ['', ' ', 'Server received, But no response!! ']:
                        if not msg.startswith('SERVER:'):
                            filteredmsg.append(msg)
            for msg in filteredmsg:
                await globalchat.send(f"{chatchannel.mention}: {msg}")
                await chatchannel.send(msg)
        except WindowsError as e:
            if e.winerror == 121:
                return await asyncio.sleep(30)
            if e.winerror == 10038:
                return await asyncio.sleep(60)

    # Just waits till bot is ready to do the loop
    @getchat.before_loop
    async def before_getchat(self):
        print("Getting crosschat loop ready.")
        await self.bot.wait_until_red_ready()

Этот код использует команду "getchat" на всех серверах и возвращает сообщения в каналы, которые я установил для указанного сервера, с которого оно пришло. Код действительно работает довольно хорошо в течение первого часа или около того после его запуска, однако я получаю сообщение «WinError 10038», которое через некоторое время начинает рассылать спам в консоли:

      [07:28:46] CRITICAL Caught unhandled exception in event loop:                                                [red.main]
                    Exception in callback _ProactorBasePipeTransport._call_connection_lost(None)
┌───────────────────────────────────────── Traceback (most recent call last) ─────────────────────────────────────────┐
│ C:\Python38\lib\asyncio\events.py:81 in _run                                                                        │
│ >  81             self._context.run(self._callback, *self._args)                                                    │
│ C:\Python38\lib\asyncio\proactor_events.py:162 in _call_connection_lost                                             │
│ > 162                 self._sock.shutdown(socket.SHUT_RDWR)                                                         │
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
OSError: [WinError 10038] An operation was attempted on something that is not a socket

Я заметил, что когда я перезапускаю бота, консоль сотни раз засыпается этой RuntimeError:

      RuntimeError: Event loop is closed
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x000002EE9F655E50>
Traceback (most recent call last):
  File "C:\Python38\lib\asyncio\proactor_events.py", line 116, in __del__
    self.close()
  File "C:\Python38\lib\asyncio\proactor_events.py", line 108, in close
    self._loop.call_soon(self._call_connection_lost, None)
  File "C:\Python38\lib\asyncio\base_events.py", line 719, in call_soon
    self._check_closed()
  File "C:\Python38\lib\asyncio\base_events.py", line 508, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed

Моя проблема / проблемы / теории: винтик работает нормально около часа, прежде чем начать спамить WinError, и огромное количество спам при перезапуске бота заставил меня подумать, что это список цикла задач, в котором слишком много задач, возможно, перегружающих бота.

Мои вопросы:

Может ли ошибка WinError быть вызвана тем, что мой список цикла задач "чат-задачи" переполнен добавленными задачами?

Правильно ли я реализовал тайм-аут, который пытался включить?

Есть ли лучший способ выполнить этот цикл задач?

Операционная система, в которой работает бот, - Windows 10, я также указал в коде следующую политику цикла событий: asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

Я использую эту библиотеку для протокола RCON: https://pypi.org/project/rcon/

Надеюсь, я прояснил, в чем моя проблема, достаточно хорошо, спасибо всем, кто может заметить мне несколько указателей, и всегда ценится немного подержать меня за руку, изучение py было ящиком проб и ошибок для пандоров, но до сих пор супер весело!

0 ответов

Другие вопросы по тегам