python open函數中newline參數實例詳解
問題的由來
我在讀pythoncsv模塊文檔 看到瞭這樣一句話
如果 csvfile 是文件對象,則打開它時應使用 newline=‘’。
其備註:如果沒有指定 newline=‘’,則嵌入引號中的換行符將無法正確解析,並且在寫入時,使用 \r\n 換行的平臺會有多餘的 \r 寫入。由於 csv 模塊會執行自己的(通用)換行符處理,因此指定 newline=‘’ 應該總是安全的。
我就在思考open函數中的newline參數的作用,因為自己之前在使用open函數時從來沒有設置過newline參數,僅從上面官方給的備註理解newline參數可以幫助處理換行符解析的問題
並且查閱得知不同操作系統換行符並不一致:
Unix 的行結束約定 ‘\n’、Windows 的約定 ‘\r\n’ 以及舊版 Macintosh 的約定 ‘\r’
打破瞭我原本觀念以為的換行符就是\n
python官方文檔對newline參數解釋:
newline 控制 universal newlines 模式如何生效(它僅適用於文本模式)。它可以是 None,‘’,‘\n’,‘\r’ 和 ‘\r\n’。它的工作原理:
從流中讀取輸入時,如果 newline 為 None,則啟用通用換行模式。輸入中的行可以以 ‘\n’,‘\r’ 或 ‘\r\n’ 結尾,這些行被翻譯成 ‘\n’ 在返回呼叫者之前。如果它是 ‘’,則啟用通用換行模式,但行結尾將返回給調用者未翻譯。如果它具有任何其他合法值,則輸入行僅由給定字符串終止,並且行結尾將返回給未調用的調用者。
將輸出寫入流時,如果 newline 為 None,則寫入的任何 ‘\n’ 字符都將轉換為系統默認行分隔符 os.linesep。如果 newline 是 ‘’ 或 ‘\n’,則不進行翻譯。如果 newline 是任何其他合法值,則寫入的任何 ‘\n’ 字符將被轉換為給定的字符串。
從這也就理解瞭為什麼原本使用open()寫的時候用\n就可以表示換行以及讀文本文件時行尾會返回\n
- 寫入的時候沒有指定newline參數會將\n翻譯成系統默認的行分割符(\r\n)
- 讀的時候沒有指定newline參數會將行分割符(\r\n)翻譯為\n
回到上文,那為什麼在讀寫csv文件時就要設置newline=''呢?
pythoncsv官方文檔解釋瞭這一問題(這也就引入瞭第二種方法解決換行的問題,我在後面會介紹到)
Dialect.lineterminator
放在 writer 產生的行的結尾,默認為 ‘\r\n’。
註解 reader 經過硬編碼,會識別 ‘\r’ 或 ‘\n’ 作為行尾,並忽略 lineterminator。未來可能會更改這一行為。
用白話說就是writerow()方法在寫入一行數據時在行尾都會跟一個默認換行符(\r\n)(即csv是將’一行數據\r\n’寫入內存,此時這一行數據還在內存中,還沒有寫入文件)之後執行代碼真正在向文件寫入時根據不同newline參數進行翻譯
而在向txt文件使用write()方法寫入內容時是我們手動添加換行符\n(內存中的數據就是我們寫入的內容,並不會隱式添加其他內容)之後執行代碼真正在向文件寫入時根據newline參數進行翻譯,這就是二者的區別
具體流程:
newline=‘’
writer.writerow(‘line’) 實際是向內存中寫入’line\r\n’ –》 執行代碼,寫入文件,根據newline=‘’,將不進行翻譯 –》文件最終寫入’line\r\n’
newline=None(默認)
f.write(‘line\n’) 直接將’line\n’寫入內存 –》 執行代碼,寫入文件,根據newline=None,將\n翻譯為\r\n –》文件最終寫入’line\r\n’
具體實例
case1: w newline=‘’ r newline=‘’
import csv with open("test.csv","w",encoding='utf-8',newline='') as csvfile: writer=csv.writer(csvfile) writer.writerow(["num","name","grade"]) writer.writerows([[1,'luke','96'],[2,'jack','85'],[3,'nick','84']]) with open("test.csv","r",encoding='utf-8',newline='') as csvfile: txtdata=csvfile.read() txtdata #>>'num,name,grade\r\n1,luke,96\r\n2,jack,85\r\n3,nick,84\r\n'
case2: w newline=‘\r’ r newline=‘’
import csv with open("test.csv","w",encoding='utf-8',newline='\r') as csvfile: writer=csv.writer(csvfile) writer.writerow(["num","name","grade"]) writer.writerows([[1,'luke','96'],[2,'jack','85'],[3,'nick','84']]) with open("test.csv","r",encoding='utf-8',newline='') as csvfile: txtdata=csvfile.read() txtdata #>>'num,name,grade\r\r1,luke,96\r\r2,jack,85\r\r3,nick,84\r\r'
case3: w newline=‘\r\n’ r newline=‘’
import csv with open("test.csv","w",encoding='utf-8',newline='\r\n') as csvfile: writer=csv.writer(csvfile) writer.writerow(["num","name","grade"]) writer.writerows([[1,'luke','96'],[2,'jack','85'],[3,'nick','84']]) with open("test.csv","r",encoding='utf-8',newline='') as csvfile: txtdata=csvfile.read() txtdata #>>'num,name,grade\r\r\n1,luke,96\r\r\n2,jack,85\r\r\n3,nick,84\r\r\n'
case4: w newline=None r newline=None
import csv with open("test.csv","w",encoding='utf-8',newline=None) as csvfile: writer=csv.writer(csvfile) writer.writerow(["num","name","grade"]) writer.writerows([[1,'luke','96'],[2,'jack','85'],[3,'nick','84']]) with open("test.csv","r",encoding='utf-8',newline=None) as csvfile: txtdata=csvfile.read() txtdata #>>'num,name,grade\n\n1,luke,96\n\n2,jack,85\n\n3,nick,84\n\n'
case5: 文件寫入為\r\r\n 文件讀取 newline=‘\r’
with open("test.csv","r",encoding='utf-8',newline='') as csvfile: txtdata=csvfile.read() txtdata #>>'num,name,grade\r\r\n1,luke,96\r\r\n2,jack,85\r\r\n3,nick,84\r\r\n' import csv with open("test.csv","r",encoding='utf-8',newline='\r') as csvfile: content = csv.reader(csvfile) for i in content: print(i)
為什麼會報錯:
csv.reader是如何讀取\r\r\n的:讀取時遇到\r認為一行結束瞭,再一次遇到\r同樣認為一行結束(因而返回瞭空串列表),遇到\n無法解釋–》報錯
case6:文件寫入為\r\r\n 文件讀取 newline=‘\n’
with open("test.csv","r",encoding='utf-8',newline='') as csvfile: txtdata=csvfile.read() txtdata #>>'num,name,grade\r\r\n1,luke,96\r\r\n2,jack,85\r\r\n3,nick,84\r\r\n' import csv with open("test.csv","r",encoding='utf-8',newline='\n') as csvfile: content = csv.reader(csvfile) for i in content: print(i)
case7:文件寫入為\r\r\n 文件讀取newline=‘\r\n’
with open("test.csv","r",encoding='utf-8',newline='') as csvfile: txtdata=csvfile.read() txtdata #>>'num,name,grade\r\r\n1,luke,96\r\r\n2,jack,85\r\r\n3,nick,84\r\r\n' import csv with open("test.csv","r",encoding='utf-8',newline='\r\n') as csvfile: content = csv.reader(csvfile) for i in content: print(i)
case8:文件寫入為\r\r 文件讀取 newline=‘\r’
with open("test.csv","r",encoding='utf-8',newline='') as csvfile: txtdata=csvfile.read() txtdata #>>'num,name,grade\r\r1,luke,96\r\r2,jack,85\r\r3,nick,84\r\r' import csv with open("test.csv","r",encoding='utf-8',newline='\r') as csvfile: content = csv.reader(csvfile) for i in content: print(i)
第二種方法:通過設置csv.writer方法中的lineterminator參數
上面提到lineterminator參數控制writer寫入每一行後跟的隱式結束符,默認為’\r\n’,因此我們需要要設置lineterminator=‘\n’,讀取時也不需要設置newline參數即可獲得想要的效果
import csv with open("test.csv","w",encoding='utf-8') as csvfile: writer=csv.writer(csvfile,lineterminator='\n') writer.writerow(["num","name","grade"]) writer.writerows([[1,'luke','96'],[2,'jack','85'],[3,'nick','84']]) with open("test.csv","r",encoding='utf-8') as csvfile: lst=csv.reader(csvfile) csvfile.seek(0) txtdata = csvfile.read() csvfile.seek(0) for i in lst: print(i) txtdata #>>'num,name,grade\n1,luke,96\n2,jack,85\n3,nick,84\n'
總結
到此這篇關於python open函數中newline參數實例詳解的文章就介紹到這瞭,更多相關python open函數newline參數內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- python csv實時一條一條插入且表頭不重復問題
- 零基礎也能看懂的python內置csv模塊教程
- Python數據讀寫之Python讀寫CSV文件
- Python中CSV文件(逗號分割)實戰操作指南
- 使用Python讀寫csv文件