背景信息:
使用之前python2的mysql库,在python3下运行,由于MariaDB重启,或者句柄失效重连MariaDB时出现bug:
在机器重启启动MariaDB后,发现API接口报错,报错日志如下:
sql error:'OperationalError' object does not support indexing,
pymysql.err.OperationalError: (2006, "MySQL server has gone away (BrokenPipeError(32, 'Broken pipe'))")
在python3 代码中增加日志打印:
logging.error('type: %s, str: %s, type: %s, args0:%s, args1:%s', type(errno), str(errno), type(errno.args), errno.args[0], errno.args[1])
打印结果:
type: <class 'pymysql.err.OperationalError'>, str: (2013, 'Lost connection to MySQL server during query'), type: <class 'tuple'>, args0:2013, args1:Lost connection to MySQL server during query
以下代码非完整代码,区别点:
在python2中pymysql.OperationalError 与python3中的使用方法不同
python2中使用pymysql.OperationalError[0]
python3中使用pymysql.err.OperationalError.args[0],多了一个args
Python 3.6.8 (default, Aug 7 2019, 17:28:10)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pymysql
>>> dir(pymysql.OperationalError)
['__cause__', '__class__', '__context__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__suppress_context__', '__traceback__', '__weakref__', 'args', 'with_traceback']
在python2中使用 pymysql.err.OperationalError[0]没问题:
def execute(sql, param=None):
try:
g_db_cur.execute(sql, param)
except pymysql.OperationalError as errno:
err_msg = 'mysql_query failed (%d: %s) [%s]\n' % (errno[0], errno[1], sql)
logging.error(err_msg)
if errno[0] == 2006 or errno[0] == 2013 or errno[0] == 2002: #CR_SERVER_GONE_ERROR, CR_SERVER_LOST, CR_CONNECTION_ERROR
#重连
else:
raise(pymysql.OperationalError, [errno[0], errinfo])
except pymysql.ProgrammingError as e:
pass
在python3中使用 pymysql.err.OperationalError.args[0]
def execute(sql, param=None):
try:
g_db_cur.execute(sql, param)
except pymysql.err.OperationalError as errno:
if errno.args[0] == 2006 or errno.args[0] == 2013 or errno.args[0] == 2002: #CR_SERVER_GONE_ERROR, CR_SERVER_LOST, CR_CONNECTION_ERROR
#重连
elif errno.args[0] == 1213: #ER_LOCK_DEADLOCK
pass
else:
pass
except pymysql.ProgrammingError as e:
pass