大家在pymysql
的 cur.fetchall()
函数通常用于获取执行 SQL 查询后的所有结果。该函数返回一个包含查询结果的元组列表。如果 cur.fetchall()
返回 None
,可能是由于以下多种问题导致的。
1、问题背景
在使用 Pymysql 库连接到 MySQL 数据库时,遇到这样的问题:
- 在一个线程中,使用
cur.fetchall()
方法查询数据库中的表名列表,并在循环中不断刷新这个列表。 - 然后,在另一个线程中,使用相同的数据库连接创建了一些新的表。
- 预期在下一个循环中,
cur.fetchall()
方法应该返回一个包含所有表名的元组,其中应该包括新创建的表。 - 但实际上,
cur.fetchall()
方法却返回了None
。
2、解决方案
这个问题的原因在于,当我创建新表时,没有显式地提交事务。导致没有将创建表的更改持久化到数据库中。因此,当我在另一个线程中使用 cur.fetchall()
方法查询表名列表时,新创建的表还没有被提交到数据库中,所以无法被查询到。
为了解决这个问题,需要在创建新表后显式地提交事务。这可以通过调用 conn.commit()
方法来实现。这样就可以将创建表的更改持久化到数据库中,并在下一个循环中使用 cur.fetchall()
方法查询到新创建的表。
以下是修改后的代码:
# 在创建新表后,显式地提交事务
conn.commit()
修改后的代码如下:
def create_flight(self):
# *********************************************************************************************
# * Create new flight table *
# *********************************************************************************************
if self.sql_write.get():
# ********************************************
# * Try to connect message *
# ********************************************
self.printLog(self.lbl_sql_write, self.LANG['tryCreateTable'], 'normal')
logging.info('Creating table for flight tracking...')
# ********************************************
# * Create name tables *
# ********************************************
event = self.oprSett['mysql']['event']
now = str(int(time.time()))
mainName = "tbl_%s_%s_" % (event, now)
trackingTable = mainName + "flighttrack"
logging.debug('Name of tracking table: %s', trackingTable)
unitsTable = mainName + "units"
logging.debug('Name of units table: %s', unitsTable)
headerTable = mainName + "header"
logging.debug('Name of header table: %s', headerTable)
# ********************************************
# * Read SQL parameter *
# ********************************************
logging.debug('Reading CSV file for table structure...')
csvFile = "config/newFlight.csv"
try:
sqlCsv = csv.reader(open(csvFile, 'rb'),
delimiter = ',',
quotechar = '"',
quoting = csv.QUOTE_ALL
)
except:
msg = csvFile
msg += "\n\n"
msg += self.LANG['e13']
tkMessageBox.showerror("Error 13", msg)
self.printLog(self.lbl_sql_write, self.LANG['e13'], 'error')
logging.error('File not found!')
#print "[Error 13] " + self.LANG['e13']
return 0
# Transfer data from CSV file into own list
sqlVars = []
for row in sqlCsv:
if len(row) == 4 and row[0][0] != "#": # No comment
sqlVars.append(row)
# *************************************************
# * Create SQL statement to create tracking table *
# *************************************************
# Head for creating new table
sql = "CREATE TABLE IF NOT EXISTS `%s` (\n" % trackingTable
sql += " `ID` int(11) NOT NULL AUTO_INCREMENT,\n" # Becomes primary key
# Parse SQL variables from CSV file
for row in sqlVars:
if len(row[2]) > 0: # Data type requires length
sql += " `%s` %s(%s) NOT NULL COMMENT '%s',\n" % (row[0], row[1], row[2], row[3])
else: # Data type not requires length
sql += " `%s` %s NOT NULL COMMENT '%s',\n" % (row[0], row[1], row[3])
# Footer of SQL statement for creating new table
sql += " PRIMARY KEY (`ID`)\n"
sql += ") ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_german1_ci AUTO_INCREMENT=0;\n"
sql += "\n"
# In debug mode print SQL statement to console
#logging.debug('SQL statement to create tracking table:\n%s', sql)
# **********************************************
# * Create SQL statement to create units table *
# **********************************************
# Head for creating new table
sql += "CREATE TABLE IF NOT EXISTS `%s` (\n" % unitsTable
sql += " `ID` int(11) NOT NULL AUTO_INCREMENT,\n" # Becomes primary key
sql += " `Dataref` varchar(10) COLLATE latin1_german1_ci NOT NULL,\n"
sql += " `Unit` varchar(10) COLLATE latin1_german1_ci NOT NULL,\n"
sql += " PRIMARY KEY (`ID`)\n"
sql += ") ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_german1_ci AUTO_INCREMENT=1 ;\n"
sql += "\n"
# Parse SQL variables from CSV file
for row in sqlVars:
# Insert units in tbl_units
sql += "INSERT INTO %s VALUES ('', '%s', '%s');\n" % (unitsTable, row[0], row[3])
sql += "\n"
# In debug mode print SQL statement to console
#logging.debug('SQL statement to create units table:\n%s', sql)
# ***********************************************
# * Create SQL statement to create header table *
# ***********************************************
# Head for creating new table
sql += "CREATE TABLE IF NOT EXISTS `%s` (\n" % headerTable
#sql += " `ID` int(11) NOT NULL AUTO_INCREMENT,\n" # Becomes primary key
sql += " `Parameter` char(21) COLLATE latin1_german1_ci NOT NULL,\n"
sql += " `Value` varchar(100) COLLATE latin1_german1_ci NOT NULL,\n"
sql += " PRIMARY KEY (`Parameter`)\n"
sql += ") ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_german1_ci AUTO_INCREMENT=1 ;\n"
sql += "\n"
# IGC syntax from: http://carrier.csi.cam.ac.uk/forsterlewis/soaring/igc_file_format/igc_format_2008.html
# Adding header parameters, some values are coming later
sql += "INSERT INTO %s VALUES ('AXXX001', '');\n" % (headerTable) # Manufacturer code
sql += "INSERT INTO %s VALUES ('HFFXA', '035');\n" % (headerTable) # Fix accuracy
sql += "INSERT INTO %s VALUES ('HFDTE', '');\n" % (headerTable) # UTC date of flight
sql += "INSERT INTO %s VALUES ('HFPLTPILOT', '');\n" % (headerTable) # Pilots name
sql += "INSERT INTO %s VALUES ('HFGTYGLIDERTYPE', 'KA8B');\n" % (headerTable) # Glider type
sql += "INSERT INTO %s VALUES ('HFGIDGLIDERID', 'D1389');\n" % (headerTable) # Glider callsign
sql += "INSERT INTO %s VALUES ('HFDTM100DATUM', 'WGS-1984');\n" % (headerTable) # GPS datum
sql += "INSERT INTO %s VALUES ('HFGPSGPS', 'X-PLANE 10');\n" % (headerTable) # Manufacturer of GPS module
sql += "INSERT INTO %s VALUES ('HFFTYFRTYPE', 'FLORIANMEISSNER,HCM');\n" % (headerTable) # Logger type
sql += "INSERT INTO %s VALUES ('HFRFWFIRMWAREVERSION', '%s');\n" % (headerTable, self.VERSION) # Firmware version
sql += "INSERT INTO %s VALUES ('HFRHWHARDWAREVERSION',
结论
- 检查 SQL 语句是否成功执行:确保查询是正确的,并且确实返回了结果。
- 使用正确的游标类型:如果需要字典格式的结果,请使用
DictCursor
。 - 确保连接和游标有效:确保连接未中断,游标没有被关闭。
- 避免多次调用
fetchall()
:确保只调用一次fetchall()
,并将结果保存以便后续使用。
通过这些步骤,我们可以排查 pymysql
中 cur.fetchall()
返回 None
的问题。