'\ r' ไม่ทำงานเป็น "lineterminator` ภายใน Python" csv.writer () "
ฉันกำลังทำงานบน Windows ฉันใช้ไฟล์ Python เพื่อสร้างไฟล์ CSV ใหม่และฉันเห็นว่าการใช้ notepad (แม้กระทั่งผ่าน Ms Excel)
import csv
data=[['fruit','quantity'],['apple',5],['banana',7],['mango',8]]
with open('d:\lineter.csv','w') as l:
w=csv.writer(l,delimiter='|',lineterminator='\r')
w.writerows(data)
ไฟล์ผลลัพธ์ใน notepad:
fruit|quantityapple|5banana|7mango|8
ผมสงสัยตรงนี้ว่าการกลับรถใช้\rงานได้หรือไม่ ??? มันทำงานเหมือนlineterminator=''ในNotepad แต่ใน excel มันทำงานเหมือน '\ n'
ผลลัพธ์ดูเหมือนจะไม่ใช้การคืนค่าขนส่ง เมื่อฉันใช้ lineterminator เป็น:
w=csv.writer(l,delimiter='|',lineterminator='*\r*\n')
ผลลัพธ์ใน notepad คือ:
fruit|quantity**
apple|5**
banana|7**
mango|8**
นี่ก็เห็นได้ชัดเช่นกัน
ใครช่วยบอกหน่อยได้ไหมว่า '\ r' ทำงานอย่างไรใน lineterminator ใน writer () หรือมีสิ่งอื่นเกิดขึ้นที่นั่น?
คำตอบ
คำตอบสั้น ๆ :
เมื่อใดควรใช้ Carriage Return (CR, \r) เทียบกับ Line Feed (LF, \n) เทียบกับทั้งสอง (CRLF \r\n) เพื่อให้บรรทัดใหม่ปรากฏในโปรแกรมแก้ไขข้อความบน Windows, Mac และ Linux:
ใครช่วยบอกหน่อยได้ไหมว่า '\ r' ทำงานอย่างไรใน lineterminator ใน writer ()
มันทำงานได้ดีในcsv.writer(). นี่ไม่ใช่ปัญหา Python, CSV หรือตัวเขียน นี่คือความแตกต่างทางประวัติศาสตร์ของระบบปฏิบัติการ (อันที่จริงการระบุว่าเป็นความแตกต่างเฉพาะโปรแกรมนั้นแม่นยำกว่า) ย้อนกลับไปในช่วงทศวรรษที่ 1960 หรือมากกว่านั้น
หรือมีสิ่งอื่นเกิดขึ้นที่นั่น?
ใช่นี่คือหนึ่ง
Notepad เวอร์ชันของคุณไม่รู้จัก Carriage Return ( \r) เป็นอักขระที่ใช้แสดงบรรทัดใหม่ดังนั้นจะไม่แสดงใน Notepad โปรแกรมแก้ไขข้อความอื่น ๆ เช่นSublime Text 3อาจเป็นไปได้แม้กระทั่งใน Windows
จนถึงประมาณปี 2018 Windows และ Notepad ต้องใช้ Carriage Return + LineFeed ( \r\n) ร่วมกันเพื่อแสดงบรรทัดใหม่ คมชัดนี้กับ Mac และ Linux \nซึ่งต้องเท่านั้น
วิธีแก้ปัญหาคือใช้\r\nสำหรับบรรทัดใหม่บน Windows และใช้\nสำหรับบรรทัดใหม่บน Mac หรือ Linux คุณยังสามารถลองใช้โปรแกรมแก้ไขข้อความอื่นเช่น Sublime Text เมื่อดูหรือแก้ไขไฟล์ข้อความหรืออัปเกรด Windows หรือ Notepad เวอร์ชันของคุณหากเป็นไปได้เนื่องจากในช่วงปี 2018 Windows Notepad เริ่มยอมรับ\rเพียงอย่างเดียวว่าเป็นเวอร์ชันเก่าที่ถูกต้อง อักขระบรรทัดใหม่สไตล์ Mac
(จากความคิดเห็นของ OP ภายใต้คำตอบนี้):
แล้วทำไมต้องให้ '\ r \ n' ???
เมื่อโปรแกรมเมอร์เขียนโปรแกรมโปรแกรมเมอร์สามารถทำให้โปรแกรมทำอะไรก็ได้ที่โปรแกรมเมอร์ต้องการให้โปรแกรมทำ เมื่อโปรแกรมเมอร์หน้าต่างที่ทำ Windows และ Notepad พวกเขาตัดสินใจที่จะทำให้โปรแกรมทำอะไรถ้ามันมี\rไม่มีอะไรถ้ามันมี\nและที่จะทำบรรทัดใหม่ถ้ามันมี\r\n ด้วยกัน มันง่ายมาก โปรแกรมกำลังทำสิ่งที่โปรแกรมเมอร์บอกให้ทำเพราะพวกเขาตัดสินใจว่าต้องการให้โปรแกรมทำงานอย่างไร ดังนั้นหากคุณต้องการบรรทัดใหม่ใน Notepad เวอร์ชันเก่า (ก่อนปี 2018) ใน Windows คุณต้องทำในสิ่งที่โปรแกรมเมอร์ต้องการให้คุณทำเพื่อให้ได้มา \r\nใช่ไหม.
สิ่งนี้ย้อนกลับไปในสมัยของผู้ผลิตเครื่องพิมพ์ดีด (อ่านส่วน "ประวัติ" และ "การเป็นตัวแทน" ที่นี่)และหน้านี้เกี่ยวกับ "เครื่องพิมพ์โทรเลข" / "เครื่องโทรพิมพ์ดีด" / "เครื่องโทรพิมพ์หรือเครื่อง TTY"ด้วย:
เครื่องพิมพ์ดีดหรือเครื่องพิมพ์ระบบเครื่องกลไฟฟ้าสามารถพิมพ์ตัวอักษรบนกระดาษและดำเนินการต่างๆเช่นเลื่อนแคร่ตลับหมึกกลับไปที่ขอบด้านซ้ายของบรรทัดเดียวกัน (การกลับแคร่ ) เลื่อนไปยังคอลัมน์เดียวกันของบรรทัดถัดไป (การป้อนบรรทัด ) และอื่น ๆ .
( แหล่งที่มา ; เน้นเพิ่ม)
ปุ่มย้อนกลับแคร่ตลับหมึกบนเครื่องพิมพ์ดีด ( \rตอนนี้อยู่บนคอมพิวเตอร์) หมายถึง: "ส่งแคร่ตลับหมึก (หัวพิมพ์) กลับไปที่จุดเริ่มต้นของบรรทัด" (หมายถึง: ด้านซ้ายสุดของหน้ากระดาษ) และกลไกการป้อนบรรทัดบน เครื่องพิมพ์ดีด ( \nตอนนี้อยู่บนคอมพิวเตอร์) หมายถึง: "ม้วนกระดาษขึ้นหนึ่งบรรทัดเพื่อที่เราจะได้พิมพ์ในบรรทัดถัดไป" หากไม่มีการดำเนินการป้อนบรรทัดเชิงกล ( \n) การส่งคืนแคร่ ( \r) เพียงอย่างเดียวจะย้ายหัวพิมพ์เชิงกลไปทางซ้ายสุดของหน้าและทำให้คุณต้องพิมพ์กลับด้านบนของคำที่คุณพิมพ์ไปแล้ว! และหากไม่มีการดำเนินการทางกลกลับของแคร่ตลับหมึก ( \rบนคอมพิวเตอร์) การดำเนินการเชิงกลป้อนบรรทัด ( \n) เพียงอย่างเดียวจะทำให้คุณพิมพ์ในคอลัมน์สุดท้ายที่ด้านขวาสุดของบรรทัดใหม่แต่ละบรรทัดบนหน้ากระดาษจะไม่สามารถคืนหัวพิมพ์ได้ ทางด้านซ้ายของหน้าอีกครั้ง! บน teletypewriter กลไฟฟ้าที่พวกเขาทั้งสองจะต้องมีการใช้กลับรถจะนำหัวพิมพ์กลับไปที่ด้านซ้ายของหน้าและการกระทำอาหารเส้นจะย้ายลงหัวพิมพ์ยังบรรทัดถัดไป ดังนั้นสมมุติโปรแกรมเมอร์ของ Windows รู้สึกว่ามันเป็นตรรกะเพื่อให้ประเพณีที่มีชีวิตอยู่และพวกเขาตัดสินใจที่จะต้องใช้ทั้งสอง\r\n เข้าด้วยกันเพื่อสร้างบรรทัดใหม่บนเครื่องคอมพิวเตอร์ตั้งแต่ที่ว่ามันจะต้องมีการทำแบบดั้งเดิมบน teletypewriter
อ่านรายละเอียดด้านล่าง
รายละเอียด:
ฉันมีความคิดบางอย่างเกี่ยวกับสิ่งที่เกิดขึ้น แต่ลองมาดู ฉันเชื่อว่าเรามี 2 คำถามที่ต้องตอบ:
- เป็น
\rจริงจะถูกเก็บไว้ในไฟล์หรือไม่ - Notepad แสดงข้อความจริง
\rหรือไม่และถ้าไม่เป็นเช่นนั้นทำไมไม่?
ดังนั้นสำหรับ # 1 ลองทดสอบบน Linux Ubuntu 20.04:
โปรแกรมนี้:
#!/usr/bin/python3
import csv
data=[['fruit','quantity'],['apple',5],['banana',7],['mango',8]]
with open('d:\lineter.csv','w') as l:
w=csv.writer(l,delimiter='|',lineterminator='\r')
w.writerows(data)
ผลิตแฟ้มนี้: D: \ lineter.csv ถ้าฉันเปิดในโปรแกรมแก้ไขข้อความ Sublime Text 3ฉันจะเห็น:
fruit|quantity
apple|5
banana|7
mango|8
จนถึงตอนนี้ดีมาก ลองดูตัวอักษรhexdumpที่บรรทัดคำสั่ง:
hexdump -cแสดง\rตัวอักษรนั่นเอง!
$ hexdump -c d\:\\lineter.csv
0000000 f r u i t | q u a n t i t y \r a
0000010 p p l e | 5 \r b a n a n a | 7 \r
0000020 m a n g o | 8 \r
0000028
คุณยังสามารถใช้hexdump -Cเพื่อแสดงตัวอักษรในฐานสิบหกแทนและอีกครั้งฉันเห็น\rในไฟล์เป็น0dอักขระฐานสิบหกซึ่งถูกต้อง
โอเคฉันบูต Windows 10 Professional ในเครื่องเสมือน Virtual Box ใน Linux และเปิดไฟล์เดียวกันใน Notepad และ .... มันก็ใช้ได้เช่นกัน! ดูภาพหน้าจอ:
แต่สังเกตส่วนที่ฉันวนซึ่งเขียนว่า "Macintosh (CR)" ฉันใช้ Windows 10 Professional เวอร์ชันล่าสุด ฉันพนันได้เลยว่าคุณกำลังใช้ Notepad เวอร์ชันเก่าซึ่งไม่มีการแก้ไขนี้และของคุณจะไม่พูดที่นี่ เนื่องจากเป็นเวลา 33 ปีแล้ว Notepad ไม่ได้จัดการ Carriage Return หรือ\rเป็นส่วนท้ายบรรทัดที่ถูกต้องดังนั้นจึงไม่แสดงเป็นเช่นนั้น ดูที่นี่: ของ Windows Notepad คงที่ 33 ปีหลังจาก: ตอนนี้ในที่สุดมันก็จัดการ Unix, Mac OS ปลายสาย
เนื่องจากความแตกต่างทางประวัติศาสตร์ย้อนหลังไปถึงเครื่องโทรพิมพ์พิมพ์ดีดและรหัสมอร์ส (อ่านส่วน "ประวัติ" และ "การเป็นตัวแทน" ที่นี่) ระบบต่างๆจึงตัดสินใจที่จะให้บรรณาธิการข้อความปฏิบัติต่อการลงท้ายบรรทัดด้วยวิธีต่างๆ จากบทความด้านบน (เน้นเพิ่ม):
Notepad ได้รับการยอมรับก่อนหน้านี้เท่านั้นที่ใช้ Windows สิ้นสุดของบรรทัด (EOL) ตัวละครโดยเฉพาะกลับบิน (CR, \ r, 0x0D) และฟีดสาย (LF \ n, 0x0A) ร่วม
สำหรับโรงเรียนเก่า Mac OS ตัวละคร EOL เป็นเพียงกลับบิน (CR, \ r, 0x0D)และสำหรับ Linux / Unix มันเป็นเพียงแค่อาหารเส้น (LF \ n, 0x0A) macOS ยุคใหม่ตั้งแต่ Mac OS X เป็นไปตามแบบแผน Unix
ดังนั้นสิ่งที่เรามีต่อไปนี้แสดงเป็นบรรทัดใหม่ในโปรแกรมแก้ไขข้อความ:
- Mac รุ่นเก่า: CR (
\r) เท่านั้น - Windows Notepad จนถึง ~ 2018: CR & LF together (
\r\n) - Linux: LF (
\n) เท่านั้น - Modern Mac: LF (
\n) เท่านั้น - Modern Windows Notepad (ปี ~ 2018 และใหม่กว่า):สถานการณ์ใด ๆ ข้างต้น
ดังนั้นสำหรับวินโดวส์เพียงแค่ติดมักจะใช้\r\nสำหรับการขึ้นบรรทัดใหม่และสำหรับMac หรือลินุกซ์เพียงแค่ติดมักจะใช้\nสำหรับการขึ้นบรรทัดใหม่ถ้าคุณกำลังพยายามที่จะรับประกันโรงเรียนเก่า (เช่น: pre-2019 :)) ความเข้ากันได้ของ Windows ของไฟล์ของคุณซึ่งในกรณีนี้คุณควรใช้\r\nสำหรับการขึ้นบรรทัดใหม่ด้วย
หมายเหตุสำหรับ Sublime Text 3 ฉันเพิ่งค้นหาการตั้งค่าในการตั้งค่า -> การตั้งค่าและพบการตั้งค่านี้:
// Determines what character(s) are used to terminate each line in new files.
// Valid values are 'system' (whatever the OS uses), 'windows' (CRLF) and
// 'unix' (LF only).
"default_line_ending": "system",
ดังนั้นหากต้องการใช้รูปแบบสำหรับระบบปฏิบัติการใดก็ตามที่คุณใช้งาน Sublime Text ค่าเริ่มต้นคือ "ระบบ" ในการบังคับให้ลงท้ายบรรทัด 'windows' (CRLF) เมื่อแก้ไขและบันทึกไฟล์ใน Sublime Text ให้ใช้สิ่งนี้:
"default_line_ending": "windows",
และหากต้องการบังคับให้ใช้การตั้งค่าการสิ้นสุดบรรทัดเดียวแบบ LF ของ unix (Mac และ Linux) ให้ใช้สิ่งนี้:
"default_line_ending": "unix",
ในโปรแกรมแก้ไข Notepad ฉันไม่พบการตั้งค่าดังกล่าวให้กำหนดค่า เป็นโปรแกรมแก้ไขที่เรียบง่ายซึ่งรองรับการสิ้นสุดบรรทัด Windows เป็นเวลา 33 ปีเท่านั้น
การอ่านเพิ่มเติม:
- https://en.wikipedia.org/wiki/Teleprinter
- https://en.wikipedia.org/wiki/Newline#History
- บรรทัดใหม่ = \ n หรือ \ r \ n หรือไม่
- เหตุใด Windows จึงใช้ CR LF
ฉันเพิ่มรหัสเพื่อแสดงค่าในไฟล์ CSV เป็นเลขฐานสิบหก:
import csv
data=[['fruit','quantity'],['apple',5],['banana',7],['mango',8]]
with open('lineter.csv','w') as l:
w=csv.writer(l,delimiter='|',lineterminator='\r')
w.writerows(data)
with open('lineter.csv', 'rb') as l:
counter = 0
while True:
char = l.read(1)
if not len(char):
break
print("%02X " % ord(char), end='')
counter += 1
if counter % 8 == 0:
print("")
เอาต์พุต
66 72 75 69 74 7C 71 75
61 6E 74 69 74 79 0D 61
70 70 6C 65 7C 35 0D 62
61 6E 61 6E 61 7C 37 0D
6D 61 6E 67 6F 7C 38 0D
อย่างที่คุณเห็น\rตัวละครอยู่ในนั้น ( 0D)
หากเราแก้ไขโค้ดเพื่อใช้'*\r*'เราจะได้ผลลัพธ์ที่คาดหวัง:
เอาต์พุต
66 72 75 69 74 7C 71 75
61 6E 74 69 74 79 2A 0D
2A 61 70 70 6C 65 7C 35
2A 0D 2A 62 61 6E 61 6E
61 7C 37 2A 0D 2A 6D 61
6E 67 6F 7C 38 2A 0D 2A
ลำดับคือ2A 0D 2A*\r*