首頁 > 軟體

python open函數中newline引數範例詳解

2022-06-22 14:03:01

問題的由來

我在讀pythoncsv模組檔案 看到了這樣一句話

如果 csvfile 是檔案物件,則開啟它時應使用 newline=‘’。
其備註:如果沒有指定 newline=‘’,則嵌入引號中的換行符將無法正確解析,並且在寫入時,使用 rn 換行的平臺會有多餘的 r 寫入。由於 csv 模組會執行自己的(通用)換行符處理,因此指定 newline=‘’ 應該總是安全的。

我就在思考open函數中的newline引數的作用,因為自己之前在使用open函數時從來沒有設定過newline引數,僅從上面官方給的備註理解newline引數可以幫助處理換行符解析的問題

並且查閱得知不同作業系統換行符並不一致:

Unix 的行結束約定 ‘n’、Windows 的約定 ‘rn’ 以及舊版 Macintosh 的約定 ‘r’

打破了我原本觀念以為的換行符就是n

python官方檔案對newline引數解釋:

newline 控制 universal newlines 模式如何生效(它僅適用於文字模式)。它可以是 None,‘’,‘n’,‘r’ 和 ‘rn’。它的工作原理:
從流中讀取輸入時,如果 newline 為 None,則啟用通用換行模式。輸入中的行可以以 ‘n’,‘r’ 或 ‘rn’ 結尾,這些行被翻譯成 ‘n’ 在返回呼叫者之前。如果它是 ‘’,則啟用通用換行模式,但行結尾將返回給呼叫者未翻譯。如果它具有任何其他合法值,則輸入行僅由給定字串終止,並且行結尾將返回給未呼叫的呼叫者。
將輸出寫入流時,如果 newline 為 None,則寫入的任何 ‘n’ 字元都將轉換為系統預設行分隔符 os.linesep。如果 newline 是 ‘’ 或 ‘n’,則不進行翻譯。如果 newline 是任何其他合法值,則寫入的任何 ‘n’ 字元將被轉換為給定的字串。

從這也就理解了為什麼原本使用open()寫的時候用n就可以表示換行以及讀文字檔案時行尾會返回n

  • 寫入的時候沒有指定newline引數會將n翻譯成系統預設的行分割符(rn)
  • 讀的時候沒有指定newline引數會將行分割符(rn)翻譯為n

回到上文,那為什麼在讀寫csv檔案時就要設定newline=''呢?

pythoncsv官方檔案解釋了這一問題(這也就引入了第二種方法解決換行的問題,我在後面會介紹到)

Dialect.lineterminator
放在 writer 產生的行的結尾,預設為 ‘rn’。
註解 reader 經過寫死,會識別 ‘r’ 或 ‘n’ 作為行尾,並忽略 lineterminator。未來可能會更改這一行為。

用白話說就是writerow()方法在寫入一行資料時在行尾都會跟一個預設換行符(rn)(即csv是將’一行資料rn’寫入記憶體,此時這一行資料還在記憶體中,還沒有寫入檔案)之後執行程式碼真正在向檔案寫入時根據不同newline引數進行翻譯
而在向txt檔案使用write()方法寫入內容時是我們手動新增換行符n(記憶體中的資料就是我們寫入的內容,並不會隱式新增其他內容)之後執行程式碼真正在向檔案寫入時根據newline引數進行翻譯,這就是二者的區別
具體流程:
newline=‘’
writer.writerow(‘line’) 實際是向記憶體中寫入’linern’ --》 執行程式碼,寫入檔案,根據newline=‘’,將不進行翻譯 --》檔案最終寫入’linern’
newline=None(預設)
f.write(‘linen’) 直接將’linen’寫入記憶體 --》 執行程式碼,寫入檔案,根據newline=None,將n翻譯為rn --》檔案最終寫入’linern’

具體範例

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,gradern1,luke,96rn2,jack,85rn3,nick,84rn'

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,graderr1,luke,96rr2,jack,85rr3,nick,84rr'

case3: w newline=‘rn’ r newline=‘’

import csv
with open("test.csv","w",encoding='utf-8',newline='rn') 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,graderrn1,luke,96rrn2,jack,85rrn3,nick,84rrn'

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,gradenn1,luke,96nn2,jack,85nn3,nick,84nn'

case5: 檔案寫入為rrn 檔案讀取 newline=‘r’

with open("test.csv","r",encoding='utf-8',newline='') as csvfile:
	txtdata=csvfile.read()
txtdata  #>>'num,name,graderrn1,luke,96rrn2,jack,85rrn3,nick,84rrn'
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是如何讀取rrn的:讀取時遇到r認為一行結束了,再一次遇到r同樣認為一行結束(因而返回了空串列表),遇到n無法解釋–》報錯

case6:檔案寫入為rrn 檔案讀取 newline=‘n’

with open("test.csv","r",encoding='utf-8',newline='') as csvfile:
    txtdata=csvfile.read()
txtdata  #>>'num,name,graderrn1,luke,96rrn2,jack,85rrn3,nick,84rrn'
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:檔案寫入為rrn 檔案讀取newline=‘rn’

with open("test.csv","r",encoding='utf-8',newline='') as csvfile:
    txtdata=csvfile.read()
txtdata  #>>'num,name,graderrn1,luke,96rrn2,jack,85rrn3,nick,84rrn'
import csv
with open("test.csv","r",encoding='utf-8',newline='rn') as csvfile:
    content = csv.reader(csvfile)
    for i in content:
        print(i)

case8:檔案寫入為rr 檔案讀取 newline=‘r’

with open("test.csv","r",encoding='utf-8',newline='') as csvfile:
    txtdata=csvfile.read()
txtdata  #>>'num,name,graderr1,luke,96rr2,jack,85rr3,nick,84rr'
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寫入每一行後跟的隱式結束符,預設為’rn’,因此我們需要要設定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,graden1,luke,96n2,jack,85n3,nick,84n'

總結

到此這篇關於python open函數中newline引數範例詳解的文章就介紹到這了,更多相關python open函數newline引數內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com