Python和MySQLdb警告

2 投票
4 回答
7102 浏览
提问于 2025-04-17 22:14

我有一个程序,它的功能是把MSSQL的数据导出,然后导入到MySQL里。我有一个导入的函数,具体是这样的:

def importMySql (mycursor,exportedfilename,table,delimiter):
    file_loc = str(sys.path[0] +"\\" +exportedfilename.lower()+".out").replace("\\", "\\\\")
    mycursor.execute("LOAD DATA LOCAL INFILE '%s' INTO TABLE %s FIELDS TERMINATED BY '%s' LINES TERMINATED BY '\r\n'" %(str(file_loc), table, delimiter))

在使用MySQLdb的时候,它会出现一些警告:

C:\Users\tfy\Documents\PyProj\UTL (Export, Import, RDF)\eic.py:98: Warning: Data truncated for column 'DateofCharges' at row 1194
  mycursor.execute("LOAD DATA LOCAL INFILE '%s' INTO TABLE %s FIELDS TERMINATED BY '%s' LINES TERMINATED BY '\r\n'" %(str(file_loc), table, delimiter))
C:\Users\tfy\Documents\PyProj\UTL (Export, Import, RDF)\eic.py:98: Warning: Data truncated for column 'DateofCharges' at row 2009
  mycursor.execute("LOAD DATA LOCAL INFILE '%s' INTO TABLE %s FIELDS TERMINATED BY '%s' LINES TERMINATED BY '\r\n'" %(str(file_loc), table, delimiter))
C:\Users\tfy\Documents\PyProj\UTL (Export, Import, RDF)\eic.py:98: Warning: Data truncated for column 'DateofCharges' at row 4793
  mycursor.execute("LOAD DATA LOCAL INFILE '%s' INTO TABLE %s FIELDS TERMINATED BY '%s' LINES TERMINATED BY '\r\n'" %(str(file_loc), table, delimiter))

但我希望能控制这些警告,只输出:

Warning: Data truncated for column 'DateofCharges' at row 1194
Warning: Data truncated for column 'DateofCharges' at row 2009
Warning: Data truncated for column 'DateofCharges' at row 4739

我查了很多资料,发现有不少信息讲解了如何创建自定义的警告。不过,我不太确定怎么才能实现我想要的效果。我并不想关闭警告,只是想“格式化”一下它们。我考虑过直接修改MySQLdb的文件,但它是以.egg格式存在的,无法直接编辑。我也尝试过使用warning.format(),但没有成功。

谢谢!

4 个回答

0

你可以在一个子进程中运行你的mysql代码吗?如果可以的话,你可以使用Python的subprocess模块来运行mysql代码,从标准输出中读取结果,并进行相应的格式化。比如,你可以使用process.stdout.readline()来读取一行输出。

你可以参考这个问题:通过STDIN/STDOUT使用Python启动和控制外部进程

1

使用 MySQLdb

你可以通过一种叫做“猴子补丁”的方法来修改 MySQLdb,以实现这个功能:

import types

def warning_check(self):
    if not self._warnings:
        self.messages = ()
        return
    self.messages = self._get_db().show_warnings()

然后在你的函数里像这样修改 Cursor 对象:

cur._warning_check = types.MethodType(warning_check, cur)

接着,当你执行完 LOAD DATA.. 后,可以打印出相关信息:

cur.execute("LOAD DATA..")
for msg in cur.messages:
    print "Warning: {msg}".format(msg=msg[2])

使用 MySQL Connector/Python

如果你用 MySQL Connector/Python,可以这样做:

cnx.get_warnings = True
cur.execute("LOAD DATA..")
for msg in cur.fetchwarnings():
    print "Warning: {msg}".format(msg=msg[2])

(注意,你需要在连接参数中设置客户端标志 client_flags=[mysql.connector.ClientFlag.LOCAL_FILES]

2

弄明白怎么使用pprint。根据提问者的解决方案,默认的警告需要被抑制,然后添加一个show_warnings的函数,最后使用新的打印格式。

from warnings import filterwarnings
import MySQLdb as mdb
from pprint import pprint

filterwarnings('ignore', category = mdb.Warning)
con = mdb.connect(...)
cur = con.cursor()
query = "Update table ..."
cur.execute(query)
con.commit()
warnings = con.show_warnings() # return in tuple type
pprint(warnings, width=100, depth=2) # width is the num of characters in each line, and depth is the level of the warnings in the tuple
5

这是我找到的最简单的方法……我也不知道为什么我一开始没想到这一点……我只是把光标发出的警告给屏蔽掉了:

import warnings
warnings.filterwarnings("ignore", category = MySQLdb.Warning)

然后我把这段代码加到了我的 importMySql 函数里:

mycursor.execute("SHOW WARNINGS")
warnings = mycursor.fetchall()
for i in range(len(warnings)):
    print "Warning - " +warnings[i][2]

撰写回答