问题描述
我正在用 Python 3 开发一个 discord 机器人,但无法正常运行。我在 1&1 服务器上托管机器人,使用 nohup python3 main.py &
启动它。机器人运行并完美运行了一段时间然后崩溃,每次都有以 RuntimeError: can't start new thread.
结尾的大量错误回溯。此外,我的代码中错误的源代码行每次都不相同。它总是来自 await [...]
行。
我在 Internet 上搜索了一段时间,但其他开发人员使用 import threading
和相关函数而我没有,我只使用 async / await
关键字。这是一个错误吗?我确定我没有达到线程限制,我一直在和几个朋友一起测试我的机器人,所以一次最多 3 到 4 个请求。机器人使用异步方法仅用于在 discord 上发送消息或反应,在任何地方都没有递归。
这是我拥有的多个 Traceback 之一。希望有人能帮助我,谢谢!
`
Ignoring exception in on_message
Traceback (most recent call last):
File "/kunden/homepages/44/d758963141/htdocs/.local/lib/python3.7/site-packages/discord/client.py",line 333,in _run_event
await coro(*args,**kwargs)
File "main.py",line 261,in on_message
await message.channel.send(lines + "```")
File "/kunden/homepages/44/d758963141/htdocs/.local/lib/python3.7/site-packages/discord/abc.py",line 905,in send
nonce=nonce,allowed_mentions=allowed_mentions)
File "/kunden/homepages/44/d758963141/htdocs/.local/lib/python3.7/site-packages/discord/http.py",line 185,in request async with self.__session.request(method,url,**kwargs) as r:
File "/kunden/homepages/44/d758963141/htdocs/.local/lib/python3.7/site-packages/aiohttp/client.py",line 1012,in __aenter__
self._resp = await self._coro
File "/kunden/homepages/44/d758963141/htdocs/.local/lib/python3.7/site-packages/aiohttp/client.py",line 483,in _request
timeout=real_timeout
File "/kunden/homepages/44/d758963141/htdocs/.local/lib/python3.7/site-packages/aiohttp/connector.py",line 523,in connect
proto = await self._create_connection(req,traces,timeout)
File "/kunden/homepages/44/d758963141/htdocs/.local/lib/python3.7/site-packages/aiohttp/connector.py",line 859,in _create_connection
req,line 967,in _create_direct_connection
traces=traces),loop=self._loop)
File "/kunden/homepages/44/d758963141/htdocs/.local/lib/python3.7/site-packages/aiohttp/connector.py",line 830,in _resolve_host
self._resolver.resolve(host,port,family=self._family)
File "/kunden/homepages/44/d758963141/htdocs/.local/lib/python3.7/site-packages/aiohttp/resolver.py",line 30,in resolve
host,type=socket.soCK_STREAM,family=family)
File "/usr/lib/python3.7/asyncio/base_events.py",line 789,in getaddrinfo
None,getaddr_func,host,family,type,proto,flags)
File "/usr/lib/python3.7/asyncio/base_events.py",line 752,in run_in_executor
executor.submit(func,*args),loop=self)
File "/usr/lib/python3.7/concurrent/futures/thread.py",line 160,in submit
self._adjust_thread_count()
File "/usr/lib/python3.7/concurrent/futures/thread.py",line 181,in _adjust_thread_count
t.start()
File "/usr/lib/python3.7/threading.py",line 847,in start
_start_new_thread(self._bootstrap,())
RuntimeError: can't start new thread
`
====== 编辑 ======
这是我的代码示例:
`
@client.event
async def on_message(message) :
global messagesId
# ===== Block self messages =====
if message.author == client.user :
return
# ===== $register =====
elif message.content == "$register" :
if not(await isRegistered(message.author.id,message.channel)) :
try :
refreshDb()
sql = "INSERT INTO player VALUES (%s,%s,0)"
dbCurs.execute(sql,(message.author.id,message.author.name))
sql = "INSERT INTO schedule(player_id) VALUES (%s)"
dbCurs.execute(sql,(message.author.id))
db.commit()
except Exception as e :
await message.channel.send("Erreur interne #9")
raise e
await message.channel.send("Tu as été enregistré.")
else :
await message.channel.send("Tu es déjà enregistré.")
# ===== $schedule =====
elif message.content == "$schedule" :
# Get player's current schedule
data = None
try :
if await isRegistered(message.author.id,message.channel) :
try :
refreshDb()
sql = "SELECT * FROM schedule WHERE player_id = %s"
dbCurs.execute(sql,(message.author.id))
data = dbCurs.fetchall()[0]
except Exception as e :
await message.channel.send("Erreur interne #4")
raise e
else :
await message.channel.send("Tu dois t'enregistrer pour utiliser cette commande.")
return
except Exception as e :
await message.channel.send("Erreur interne #5")
raise e
# Create lines
text = "<@{}>\n{}".format(message.author.id,getScheduleText(data,1))
sentMessage = await message.channel.send(text)
# register message's id
messagesId[sentMessage.id] = message.author.id
# Add reactions
i = 0
keys = list(cols.keys())
for key in keys :
await sentMessage.add_reaction(bytes.decode(numbers[i]))
i += 1
# Register every messages id and delete everyone after 60 sec
await deleteSched(sentMessage)
`
解决方法
您的代码显然使用线程,通过线程池执行器;这旨在运行持久任务,但让主 asyncio 线程可用于处理更多事件。当您的代码遇到某个 await
条件时,总是会在执行程序中创建新线程,因为这是事件循环可以自由工作的唯一时间。
所以...,您在执行程序中运行的任务似乎并未结束,而且您最终会遇到很多过时的线程。没有看到代码,我想我们不能说更多。