一.CSV模塊介紹
CSV (Comma Separated Values) 格式是電子表格和數(shù)據(jù)庫(kù)中最常見(jiàn)的輸入、輸出文件格式。在 RFC 4180規(guī)范推出的很多年前,CSV 格式就已經(jīng)被開始使用了,由于當(dāng)時(shí)并沒(méi)有合理的標(biāo)準(zhǔn)米者,不同應(yīng)用程序讀寫的數(shù)據(jù)會(huì)存在細(xì)微的差別。這種差別讓處理多個(gè)來(lái)源的 CSV 文件變得困難。但盡管分隔符會(huì)變化蔓搞,此類文件的大致格式是相似的胰丁,所以編寫一個(gè)單獨(dú)的模塊以高效處理此類數(shù)據(jù),將程序員從讀寫數(shù)據(jù)的繁瑣細(xì)節(jié)中解放出來(lái)是有可能的喂分。
csv模塊定義的函數(shù):
函數(shù)名 | 函數(shù)用途 |
---|---|
csv.reader(csvfile, dialect='excel', **fmtparams) | 返回一個(gè) reader 對(duì)象锦庸,該對(duì)象將逐行遍歷 csvfile |
csv.writer(csvfile, dialect='excel', **fmtparams) | 返回一個(gè) writer 對(duì)象,該對(duì)象負(fù)責(zé)將用戶的數(shù)據(jù)在給定的文件類對(duì)象上轉(zhuǎn)換為帶分隔符的字符串 |
csv.register_dialect(name[, dialect[, **fmtparams]]) | 將 name 與 dialect 關(guān)聯(lián)起來(lái)妻顶。name 必須是字符串酸员。 |
csv.unregister_dialect(name) | 從變種注冊(cè)表中刪除 name 對(duì)應(yīng)的變種。 |
csv.get_dialect(name) | 返回 name 對(duì)應(yīng)的變種讳嘱。 |
csv.list_dialects() | 返回所有已注冊(cè)變種的名稱 |
csv.field_size_limit([new_limit]) | 返回解析器當(dāng)前允許的最大字段大小 |
csv模塊定義的類:
類名 | 類描述 |
---|---|
class csv.DictReader | 創(chuàng)建一個(gè)對(duì)象幔嗦,其操作類似于常規(guī) reader 但會(huì)將每行中的信息映射到一個(gè) OrderedDict ,其中的鍵由可選的 fieldnames 形參給出沥潭。 |
class csv.DictWriter | 創(chuàng)建一個(gè)對(duì)象邀泉,該對(duì)象在操作上類似常規(guī) writer,但能將字典映射到輸出行 |
class csv.Dialect |
Dialect 類是主要依賴于其屬性的容器類钝鸽,用于將定義好的參數(shù)傳遞給特定的 reader 或 writer 實(shí)例汇恤。 |
class csv.excel |
excel 類定義了 Excel 生成的 CSV 文件的常規(guī)屬性。它在變種注冊(cè)表中的名稱是 'excel'
|
class csv.excel_tab |
excel_tab 類定義了 Excel 生成的拔恰、制表符分隔的 CSV 文件的常規(guī)屬性因谎。它在變種注冊(cè)表中的名稱是 'excel-tab' 。 |
class csv.unix_dialect |
unix_dialect 類定義了在 UNIX 系統(tǒng)上生成的 CSV 文件的常規(guī)屬性颜懊,即使用 '\n' 作為換行符财岔,且所有字段都有引號(hào)包圍。 |
class csv.Sniffer |
Sniffer 類用于推斷 CSV 文件的格式河爹。 |
csv模塊定義了以下常量:
csv.QUOTE_ALL | 指示 writer 對(duì)象給所有字段加上引號(hào) |
csv.QUOTE_MINIMAL | 指示 writer 對(duì)象僅為包含特殊字符(例如 定界符匠璧、引號(hào)字符 或 行結(jié)束符 中的任何字符)的字段加上引號(hào)。 |
csv.QUOTE_NONNUMERIC | 指示 writer 對(duì)象為所有非數(shù)字字段加上引號(hào)咸这。 |
csv.QUOTE_NONE | 指示 writer 對(duì)象不使用引號(hào)引出字段夷恍。 |
csv模塊定義了以下異常:
exception csv.Error
該異常可能由任何發(fā)生錯(cuò)誤的函數(shù)拋出媳维。
二.csv模塊實(shí)例
2.1 將mysql查詢到的數(shù)據(jù)導(dǎo)出到本地csv文件
代碼:
import csv
import pymysql
# 創(chuàng)建mysql連接
conn = pymysql.connect(host='localhost', port=3306, user='root', passwd='abc123',db='zqs')
cursor = conn.cursor()
sql1 = "select empno,ename , mgr,hiredate from emp where 1 = 1"
headers = ["empno","ename","mgr","hiredate"]
cursor.execute(sql1)
rows = cursor.fetchall()
with open('E:\python\emp.csv', 'w', newline='') as csvfile:
my_csv_write = csv.writer(csvfile, delimiter=',', quoting=csv.QUOTE_MINIMAL)
my_csv_write.writerow(headers)
my_csv_write.writerows(rows)
conn.commit()
# 關(guān)閉連接
cursor.close()
conn.close()
測(cè)試記錄:
如下查看可得知酿雪,數(shù)值、字符侄刽、日期以及空值都正常導(dǎo)出到了csv文件
2.2 將本地csv文件導(dǎo)入到mysql數(shù)據(jù)庫(kù)
對(duì)于CSV中空值的處理
數(shù)值型空值执虹,必須是 %s 而不能使用 '%s'
字符型空值以及時(shí)間類型空值,必須是 %s 而不能使用 '%s',但是錄入其它非空的字符唠梨,又必須用'%s'
用excel打開csv文件截圖:
從上圖可以看到 ename列是字符型空值,mgr侥啤、comm列是數(shù)值型空值当叭,hiredate是日期型空值
Python代碼:
db_setting.py
# 存儲(chǔ)數(shù)據(jù)庫(kù)信息
# 創(chuàng)建一個(gè)列表嵌套列表,存儲(chǔ)數(shù)據(jù)庫(kù)信息
# 依次是 數(shù)據(jù)庫(kù)備注茬故、ip、端口蚁鳖、磺芭、用戶名、密碼醉箕、登陸數(shù)據(jù)庫(kù)名
mysql_msg = [['本地mysql', 'localhost', 3306 , 'root', 'abc123', 'zqs'],
['遠(yuǎn)程mysql', '10.31.1.123', 3306, 'root', 'abc123', 'test']
]
mysql_test3.py
import pymysql, datetime
import csv
import db_setting
import math
from numpy import nan as NaN
class mysql_class(object):
"""對(duì)mysql的操作創(chuàng)建一個(gè)類"""
def __init__(self, name):
self.name = name
def login_mysql(self):
"""獲取mysql的登陸信息"""
mysql_msg = db_setting.mysql_msg
name = self.name
for i in range(0,len(mysql_msg) ):
exec_db = mysql_msg[i]
if name == exec_db[0]:
# 根據(jù)輸入連接數(shù)據(jù)庫(kù)
return exec_db
# conn = pymysql.connect(host=exec_db[1], port=exec_db[2], user=exec_db[3], passwd=exec_db[4],db=exec_db[5])
else:
pass
def csv_insert_mysql(self):
"""將csv的文件錄入到mysql"""
exec_db = mysql_class.login_mysql(self)
conn = pymysql.connect(host=exec_db[1], port=exec_db[2], user=exec_db[3], passwd=exec_db[4], db=exec_db[5] ,charset='utf8')
cursor = conn.cursor()
# 測(cè)試了數(shù)值類型還是會(huì)存在問(wèn)題, yyyy/mm/dd 這類時(shí)間格式測(cè)試了也不會(huì)有問(wèn)題的
# 數(shù)值型空值钾腺,必須是 %s 而不能使用 '%s'
# 字符型空值以及時(shí)間類型空值,必須是 %s 而不能使用 '%s',但是錄入其它非空的字符讥裤,又必須用'%s'
sql = ""
sql1 = "insert into emp_csv(empno, ename, job, mgr, hiredate, sal, comm, deptno) values ('%s', %s, '%s', %s, '%s', '%s', %s, '%s') "
sql2 = "insert into emp_csv(empno, ename, job, mgr, hiredate, sal, comm, deptno) values ('%s', '%s', '%s', %s, '%s', '%s', %s, '%s') "
sql3 = "insert into emp_csv(empno, ename, job, mgr, hiredate, sal, comm, deptno) values ('%s', '%s', '%s', %s, %s, '%s', %s, '%s') "
filename = 'E:/python/file_test/emp_csv_2.csv'
with open(filename, 'r') as f:
reader = csv.reader(f)
# print(type(reader))
for i, row in enumerate(reader):
# 剔除第一行的列頭
if i > 0:
empno = row[0]
if row[1]:
ename = row[1]
else:
ename = 'NULL'
job = row[2]
if row[3]:
mgr = row[3]
else:
mgr = 'NULL'
if row[4]:
hiredate = row[4]
else:
hiredate = 'NULL'
sal = row[5]
if row[6]:
comm = row[6]
else:
comm = 'NULL'
deptno = row[7]
print(empno, ename, job, mgr , hiredate, sal, comm , deptno)
# 遍歷列表,循環(huán)錄入數(shù)據(jù)
if not row[1]:
sql = sql1
if not row[4]:
sql = sql3
# 如果存在兩列同時(shí)為null的情況,還得繼續(xù)增加判斷條件
if row[1]:
if row[4]:
sql = sql2
cursor.execute(sql % (empno, ename, job, mgr, hiredate, sal, comm, deptno))
conn.commit()
# 關(guān)閉連接
cursor.close()
conn.close()
if __name__ == '__main__':
my_class1 = mysql_class('本地mysql')
my_class1.csv_insert_mysql()