Spa*_*row 5 python-3.x peewee pymysql digital-ocean discord.py
我是一名 Discord 机器人开发人员,最近完成了一个订单。客户端在其服务器上设置应用程序时最初没有问题,但根据他们的说法,在运行“大约三个小时”后,程序开始吐出特定的堆栈跟踪错误并且不再接受命令。
该机器人使用 Discord.py 构建,并使用 Peewee 作为 ORM,使用 PyMySQL 作为数据库驱动程序。客户端运行它的服务器由 DigitalOcean 托管,如果需要有关硬件等的任何信息,客户端可以根据请求向我提供该信息。我们已经尝试卸载并重新安装所有依赖项,以及尝试它们的不同发行版,但错误仍然存在。
这是客户端正在接收的确切跟踪:
File "/usr/local/lib/python3.6/dist-packages/peewee.py", line 2666, in __exit__
reraise(new_type, new_type(*exc_args), traceback)
File "/usr/local/lib/python3.6/dist-packages/peewee.py", line 179, in reraise
raise value.with_traceback(tb)
File "/usr/local/lib/python3.6/dist-packages/peewee.py", line 2875, in execute_sql
cursor.execute(sql, params or ())
File "/usr/local/lib/python3.6/dist-packages/pymysql/cursors.py", line 170, in execute
result = self._query(query)
File "/usr/local/lib/python3.6/dist-packages/pymysql/cursors.py", line 328, in _query
conn.query(q)
File "/usr/local/lib/python3.6/dist-packages/pymysql/connections.py", line 516, in query
self._execute_command(COMMAND.COM_QUERY, sql)
File "/usr/local/lib/python3.6/dist-packages/pymysql/connections.py", line 750, in _execute_command
raise err.InterfaceError("(0, '')")
peewee.InterfaceError: (0, '')
Run Code Online (Sandbox Code Playgroud)
我的 database.py 文件中的相关部分,其中打开了数据库连接:
File "/usr/local/lib/python3.6/dist-packages/peewee.py", line 2666, in __exit__
reraise(new_type, new_type(*exc_args), traceback)
File "/usr/local/lib/python3.6/dist-packages/peewee.py", line 179, in reraise
raise value.with_traceback(tb)
File "/usr/local/lib/python3.6/dist-packages/peewee.py", line 2875, in execute_sql
cursor.execute(sql, params or ())
File "/usr/local/lib/python3.6/dist-packages/pymysql/cursors.py", line 170, in execute
result = self._query(query)
File "/usr/local/lib/python3.6/dist-packages/pymysql/cursors.py", line 328, in _query
conn.query(q)
File "/usr/local/lib/python3.6/dist-packages/pymysql/connections.py", line 516, in query
self._execute_command(COMMAND.COM_QUERY, sql)
File "/usr/local/lib/python3.6/dist-packages/pymysql/connections.py", line 750, in _execute_command
raise err.InterfaceError("(0, '')")
peewee.InterfaceError: (0, '')
Run Code Online (Sandbox Code Playgroud)
我的 bot.py 文件中的相关部分,特别是首次打开机器人时运行的机器人启动功能,以及创建和启动机器人客户端的行:
import discord
from peewee import *
from config import db_host, db_port, mysql_db_name, \
mysql_db_username, mysql_db_password
db_connection = MySQLDatabase(
mysql_db_name,
user = mysql_db_username,
password = mysql_db_password,
host = db_host,
port = db_port
)
def create_db_tables():
# create_tables() does safe creation by default, and will simply not create
# table if it already exists
db_connection.create_tables([User])
Run Code Online (Sandbox Code Playgroud)
根据客户的说法,重新启动机器人可以暂时解决问题,并且在错误再次启动之前它可以正常运行几个小时。一旦错误开始,机器人就不再响应任何传入的命令,如果抛出足够多的错误,则会完全崩溃。
此错误的典型原因是什么,应采取哪些步骤来修复导致该错误的原因?
错误出现的时间让我想起了我在与数据库通信时也遇到的问题。
问题可能是,由于连接在机器人启动时打开(甚至在程序开始执行时)并且偶尔使用,数据库可能会关闭连接,因此任何进一步的执行都会导致错误。为了解决这个问题,我为数据库类的所有方法创建了这个装饰器
def ensures_connected(f):
def wrapper(*args):
args[0].connection.ping(reconnect=True, attempts=3, delay=2)
return f(*args)
return wrapper
Run Code Online (Sandbox Code Playgroud)
放置在必须与数据库通信的任何方法或函数之上。
该行args[0].connection.ping(reconnect=True, attempts=3, delay=2)意味着我们将调用self.connection(因为它是调用时传递给该方法的第一个参数)方法ping,该方法允许在连接断开时重新连接。
self.connection在我的代码中是由方法调用MySQLConnection.connect返回的对象,应该等同于您的对象db_connection
该装饰器应放置在方法定义之上,如下例所示:
def ensures_connected(f):
def wrapper(*args):
args[0].connection.ping(reconnect=True, attempts=3, delay=2)
return f(*args)
return wrapper
class Database:
def __init__(self):
self.connection = mysql.connector.connect(
user=self.username, password=password, host=self.host, database=self.database)
# ...
@ensures_connected
def is_member_registered(self, guild: Guild, member: Member):
# ...
return
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
932 次 |
| 最近记录: |