我是靠谱客的博主 明理棒球,最近开发中收集的这篇文章主要介绍python TorMySQL 异常处理不显示traceback的坑,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

背景:

最近找到一个异步数据库驱动,TorMySQL,ab测试后效果是其他几个异步驱动最好的,遂用之。

因为尽可能业务逻辑层和数据访问层分离,并且考虑到单一负责原则,把每一个数据库的操作简称为service,如user_service,work_service之类的。

很多情况下,每一个逻辑业务都是要N个service合作才完成的。

所以就不在单个service中try except,而是在业务逻辑层中try except。

一是:

少写很多代码,不然每一个service都要try except之后,logging.error(ex, exc_info=1)打印traceback,然后再raise ex,多麻烦...

二是:

考虑到很多情况下有用到事务,只能在业务逻辑层捕获exception,捕获到就conn.rollback(),没捕获到就conn.commit()。


然而,我上面这种设计竟然没捕获到traceback,简直匪夷所思。

好了,背景交代完毕。


版本:

python 2.7
tormysql==0.2.9
tornado==4.2


测试1:

import logging
from tornado.ioloop import IOLoop
from tornado import gen
import tormysql
pool = tormysql.ConnectionPool(
max_connections = 20, #max open connections
idle_seconds = 7200, #conntion idle timeout time, 0 is not timeout
wait_connection_timeout = 3, #wait connection timeout
host = "127.0.0.1",
user = "root",
passwd = "123qwe",
db = "chanzai_dev",
charset = "utf8"
)
@gen.coroutine
def aa(conn):
sql = "SELECT * FROM UserDevice where user_id = %s" % 100002
with conn.cursor() as cursor:
yield cursor.execute(sql)
cursor.fetchone()
# 下面是故意出错代码
a = '10'
b = a / 10
print b
@gen.coroutine
def bb(conn):
yield aa(conn)
@gen.coroutine
def cc():
with (yield pool.Connection()) as conn:
try:
yield bb(conn)
except KeyError:
pass
except Exception, ex:
yield conn.rollback()
logging.error(ex, exc_info=1)
ioloop = IOLoop.instance()
ioloop.run_sync(cc)
测试结果:

G:projectsmyApptmp>a.py
ERROR:root:unsupported operand type(s) for /: 'str' and 'int'
None

测试2:

import logging
from tornado.ioloop import IOLoop
from tornado import gen
import tormysql
pool = tormysql.ConnectionPool(
max_connections = 20, #max open connections
idle_seconds = 7200, #conntion idle timeout time, 0 is not timeout
wait_connection_timeout = 3, #wait connection timeout
host = "127.0.0.1",
user = "root",
passwd = "123qwe",
db = "chanzai_dev",
charset = "utf8"
)
@gen.coroutine
def aa(conn):
sql = "SELECT * FROM UserDevice where user_id = %s" % 100002
with conn.cursor() as cursor:
yield cursor.execute(sql)
cursor.fetchone()
# 下面是故意出错代码
a = '10'
b = a / 10
print b
@gen.coroutine
def bb(conn):
yield aa(conn)
@gen.coroutine
def cc():
with (yield pool.Connection()) as conn:
try:
yield bb(conn)
except KeyError:
pass
except Exception, ex:
logging.error(ex, exc_info=1)
yield conn.rollback()
ioloop = IOLoop.instance()
ioloop.run_sync(cc)
测试结果:
G:projectsmyApptmp>a.py
ERROR:root:unsupported operand type(s) for /: 'str' and 'int'
Traceback (most recent call last):
File "G:projectsmyApptmpa.py", line 40, in cc
yield bb(conn)
File "G:Python27libsite-packagestornadogen.py", line 1015, in run
value = future.result()
File "G:Python27libsite-packagestornadoconcurrent.py", line 237, in result
raise_exc_info(self._exc_info)
File "G:Python27libsite-packagestornadogen.py", line 1021, in run
yielded = self.gen.throw(*exc_info)
File "G:projectsmyApptmpa.py", line 34, in bb
yield aa(conn)
File "G:Python27libsite-packagestornadogen.py", line 1015, in run
value = future.result()
File "G:Python27libsite-packagestornadoconcurrent.py", line 237, in result
raise_exc_info(self._exc_info)
File "G:Python27libsite-packagestornadogen.py", line 1024, in run
yielded = self.gen.send(value)
File "G:projectsmyApptmpa.py", line 30, in aa
b = a / 10
TypeError: unsupported operand type(s) for /: 'str' and 'int'
G:projectsmyApptmp>


观察结果:

根据两个测试,其实只改了一个地方,就是:

except Exception, ex:
logging.error(ex, exc_info=1)
yield conn.rollback()

except Exception, ex:
yield conn.rollback()
logging.error(ex, exc_info=1)
前者才能得到想要的结果,为什么有后者这种写法呢,是因为,想着对于数据库的操作出错了还是尽早rollback为好,没想到就踩了坑。



原因分析:

看了下pymysql的connections.py源码(因为TorMySQL是对pymysql的封装),发现确实有很多try except,我都不用具体往下看了,因为很大可能性是我们的ex被pymysql给捕获到了,但是raise出来的是pymysql处理过的ex,所以看不到traceback...吧
解决方案就是先logging.error(ex, exc_info=1) 再 yield conn.rollback()



最后

以上就是明理棒球为你收集整理的python TorMySQL 异常处理不显示traceback的坑的全部内容,希望文章能够帮你解决python TorMySQL 异常处理不显示traceback的坑所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(39)

评论列表共有 0 条评论

立即
投稿
返回
顶部