将mysql与python一起使用时,您可能希望使用mysqlclient库,这是大多数人所做的且效果甚好。或者,如果您正在使用官方的mysql 8 connector/python包,情况会略有不同,但可能已经在mysql 8中支持的功能还尚未出现在mysqlclient中。
您的sql可能是手动编写的,也可能是使用sql alchemy,django或其他包生成的。如果是后者,为了便于交互式调试,查看发送到数据库的实际sql字符串的方法可能会很有用。
使用 mysqlclient
如果mysqlclient与python一起使用,则cursor类内部以该类()中的_query(self, q)方法将sql发送到服务器。
该方法_query(self, q)本身会更新cursor的_executed成员,存储发送到服务器的文本查询字符串。但它仅在发送查询后才会这样做。出错时,将引发异常且_executed的更新失败( )。
若要访问实际的查询字符串,请定义一个类debugcursor,并使用连接**kwargs指定它。在debugcursor中,这么做是有必要的。
import mysqldb
import mysqldb.cursors
class debugcursor(mysqldb.cursors.dictcursor):
def _query(self, q):
print(f"debug: {q}")
super()._query(q)
db_config = dict(
host="localhost",
user="kris",
passwd="secret",
db="kris",
cursorclass=debugcursor, # referenced class must be defined before
)
db = mysqldb.connect(**db_config)
c = db.cursor(()
sql = "select d from testtable where id = 3"
c.execute(sql)
print(c.fetchall())
在类debugcursor中,我们选择继承ursor。重写_query(self, q)方法,打印查询字符串q,然后调用父类实现。
输出:
$ python3 probe.py
debug: b'select d from testtable where id = 3'
({'d': 'drei'},)
即使查询字符串无效或包含语法错误,我们也可以使用它来跟踪所有被执行之前的文本sql。
使用 mysql connector/python
如果您使用oracle mysql connector/python连接到数据库,则可以在内部使用cython或协议的pure python实现。
这两种实现的行为略有不同。只有pure python实现可以在所有情况下轻松调试。因此,请务必使用**kwargs连接指定use_pure=true。
原始sql语句将在cursor的_executed成员中找到。如果您使用的是多语句,它们将记录在_executed_list中。
我们写为:
import mysql.connector
import mysql.connector.errors
db_config = dict(
host="127.0.0.1",
user="kris",
passwd="geheim",
db="kris",
use_pure=true,
)
db = mysql.connector.connect(**db_config)
c = db.cursor()
print("=== valid sql: ")
sql = "select d from testtable where id = 3"
c.execute(sql)
print(f"debug: {c._executed}")
print(c.fetchall())
print()
print("=== invalid sql: ")
sql = "syntaxerror d from testtable where id = 3"
try:
c.execute(sql)
except mysql.connector.errors.programmingerror as e:
print(f"debug: {c._executed}")
print(f"error: {e}")
输出如下所示:
python3 probe.py
=== valid sql:
debug: b'select d from testtable where id = 3'
[('drei',)]
=== invalid sql:
debug: b'syntaxerror d from testtable where id = 3'
error: 1064 (42000): you have an error in your sql syntax; check the manual that corresponds to your mysql server version for the right syntax to use near 'syntaxerror d from testtable where id = 3' at line 1
同样,我们可以使用它来跟踪原始sql并识别实际生成的sql语法,这样会更容易。这将允许我们选取文本sql字符串,并以交互方式进行调试。
如果sql格式不正确,则在不带use_pure=true的情况下运行时,相同的程序将无法正确更新c._executed。它将生成以下输出,这对于调试毫无价值:
$ python3 probe.py
=== valid sql:
debug: b'select d from testtable where id = 3'
[('drei',)]
=== invalid sql:
debug: b'select d from testtable where id = 3'
error: 1064 (42000): you have an error in your sql syntax; check the manual that corresponds to your mysql server version for the right syntax to use near 'syntaxerror d from testtable where id = 3' at line 1
请注意,c._executed是怎样做到仍然保存前一个语句,而不是实际出错的语句。
原文标题:debugging sql in python
原文作者:kristian köhntopp
原文链接:https://blog.koehntopp.info/2022/03/24/debugging-sql-in-python.html#using-mysqlclient