如何解决WinError 10038 和可能执行不力的任务循环超时? (discord.py 的东西也是) 在这里编码的菜鸟
我才 3 周多就开始自学 Python,所以请耐心等待 :')
我有一个任务循环,在机器人运行时无限期地每 5 秒运行一次,机器人运行使用名为“cogs”的模块的“RED discord bot”框架,这是我一直在研究的部分,这是部分我的代码一直有问题:
# Crosschat loop logic
@tasks.loop(seconds=3)
async def getchat(self):
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 option #1 using discord.ext.tasks"""
# await self.getchatrcon(guild,# guildsettings[cluster]["servers"][server]["cluster"],# guildsettings[cluster]["servers"][server]
# )
"""Loop option #2 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
try:
tasks = asyncio.gather(*chattask)
if len(asyncio.all_tasks()) > 60:
print(f"Task list full{len(asyncio.all_tasks())},skipping iteration")
return
await asyncio.wait_for(tasks,timeout=2)
except asyncio.TimeoutError as e:
print(f"task timeout: {e}")
await asyncio.sleep(5)
# Rcon function for getchat loop,parses the response to send to 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']
)
except OSError as e:
if e.osrror == 121:
return await asyncio.sleep(30)
if e.osrror == 10038:
return await asyncio.sleep(60)
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)
# Just waits till bot is ready to do the chat 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 发送垃圾邮件之前,cog 可以正常工作大约一个小时,而在机器人重启时发送的大量 RuntimeError: Event loop is closed
使我认为这是任务循环列表中的任务过多,可能使机器人不堪重负。>
我的问题是:
WinError 是否可能是由于我的“chattask”任务循环列表被附加任务溢出?
我是否正确实施了我尝试包含的超时?
有没有更好的方法来完成这个任务循环?
机器人运行的操作系统是 Windows 10,我还在代码中指定了以下事件循环策略:asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
我将此库用于 RCON 协议:https://pypi.org/project/rcon/
我希望我能很好地澄清我的问题,感谢任何能发现我一些指针并握住我手的人总是很感激,学习 py 一直是一个反复试验的潘多拉盒子,但到目前为止超级有趣!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。