CSV ใน Python เพิ่มการรับคืนพิเศษใน Windows


231
import csv
outfile = file('test.csv', 'w')
writer = csv.writer(outfile, delimiter=',', quoting=csv.QUOTE_MINIMAL)
writer.writerow(['hi','dude'])
writer.writerow(['hi2','dude2'])
outfile.close()

มันสร้างไฟล์test.csvโดยเพิ่มเป็นพิเศษ\rในแต่ละแถวเช่น:

test.csv

hi,dude\r\r\nhi2,dude2\r\r\n

แทนการคาดหวัง:

hi,dude\r\nhi2,dude2\r\n

ทำไมสิ่งนี้ถึงเกิดขึ้นหรือนี่คือพฤติกรรมที่ต้องการจริง ๆ หรือ?

บันทึก:

  • พฤติกรรมนี้สามารถเกิดขึ้นได้กับ Python 2 หรือ 3

สำเนาซ้ำที่เป็นไปได้ของPython 2 CSV writer จะสร้างตัวคั่นบรรทัดผิดบน Windows
John Y

คำตอบ:


311

Python 3:

  • ตามที่อธิบายไว้โดยYiboYangตั้งnewline=''
with open('output.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    ...
  • ตามที่ระบุไว้ในข้อคิดเห็นโดยCoDEmanXตั้งค่าnewline='\n'
with open('output.csv', 'w', newline='\n', encoding='utf-8') as f:
    writer = csv.writer(f)
    ...

Python 2:

บน Windows, เสมอเปิดไฟล์ของคุณในโหมดไบนารี ( "rb"หรือ"wb") ก่อนที่จะผ่านพวกเขาไปหรือcsv.readercsv.writer

แม้ว่าไฟล์ดังกล่าวจะเป็นไฟล์ข้อความ แต่ CSV ถือเป็นรูปแบบไบนารีโดยห้องสมุดที่เกี่ยวข้องโดยมี\r\nการแยกบันทึก หากตัวคั่นนั้นถูกเขียนในโหมดข้อความ Python runtime จะแทนที่\nด้วย\r\nดังนั้นจึง\r\r\nสังเกตได้ในไฟล์

ดูคำตอบก่อนหน้านี้


3
สิ่งนี้ดีสำหรับ ASCII แต่จะหยุดการเข้ารหัสเช่น UTF-8 โซลูชันของ Jason ด้านล่างใช้งานได้สำหรับฉัน
Tom

66
ในหลาม 3 open(..., "w", newline="\n", encoding="utf-8")ผมก็สามารถที่จะแก้ไขได้โดยใช้ตัวเลือกต่อไปนี้สำหรับวัตถุไฟล์: newlineสามารถเป็นสตริงว่างได้ผลลัพธ์เดียวกัน "wb"ไม่ทำงานใน Python 3 สตริงและส่วนต่อประสานบัฟเฟอร์ไม่เข้ากัน
CodeManX

วิธีที่สง่างามในการจัดการการรับคืนรถพิเศษ
ForeverLearner

2
ใช้งานไม่ได้กับ Python2 ดังนั้นหากคุณต้องการใช้งานร่วมกันได้กับทั้ง 2 และ 3 ให้ใช้คำตอบที่ @ jason-r-coombs:writer = csv.writer(f, lineterminator='\n')
yossiz74

4
นี่เป็นความอัปยศจริงที่ API พื้นฐานธรรมดาและธรรมดาดังกล่าวไม่ทำงานตามที่ต้องการ
SomethingSomething

248

ในขณะที่@ john-machinให้คำตอบที่ดีก็ไม่ใช่วิธีที่ดีที่สุดเสมอไป ตัวอย่างเช่นมันใช้งานไม่ได้กับ Python 3 เว้นแต่คุณจะเข้ารหัสข้อมูลทั้งหมดของคุณไปยังเครื่องเขียน CSV นอกจากนี้ยังไม่ได้แก้ไขปัญหาหากสคริปต์ต้องการใช้ sys.stdout เป็นสตรีม

ฉันขอแนะนำให้ตั้งค่าแอตทริบิวต์ 'lineterminator' แทนเมื่อสร้างผู้เขียน:

import csv
import sys

doc = csv.writer(sys.stdout, lineterminator='\n')
doc.writerow('abc')
doc.writerow(range(3))

ตัวอย่างนั้นจะทำงานกับ Python 2 และ Python 3 และจะไม่สร้างอักขระขึ้นบรรทัดใหม่ที่ไม่ต้องการ อย่างไรก็ตามโปรดทราบว่ามันอาจสร้างบรรทัดใหม่ที่ไม่พึงประสงค์ (ละเว้นอักขระ LF บนระบบปฏิบัติการ Unix)

อย่างไรก็ตามในกรณีส่วนใหญ่ฉันเชื่อว่าพฤติกรรมนั้นเป็นที่นิยมและเป็นธรรมชาติมากกว่าการใช้ CSV ทั้งหมดในรูปแบบไบนารี ฉันให้คำตอบนี้เป็นทางเลือกสำหรับการพิจารณาของคุณ


6
นี่คือคำตอบที่ดีที่สุดในความคิดของฉัน มันมีปัญหาใน Unix แล้วจะเรียก sys.platform และจัดการกับมันแบบไดนามิกได้อย่างไร?
sovemp

4
คำตอบที่ดีที่สุดในความคิดของฉันเช่นกันและ lineterminator = '\ n' ทำงานได้อย่างสวยงาม
eikonal

1
คุณสามารถยกตัวอย่างปัญหาที่เกิดขึ้นถ้าคุณไม่ "เข้ารหัสอินพุตทั้งหมดของคุณไปที่ตัวเขียน CSV" ได้หรือไม่?
Stephen

ระวัง: การใช้วิธีการนี้\rจะไม่ได้หลบหนีอีกต่อไป! ดูเหมือนว่านี่จะเป็นจุดบกพร่องcsvwriterแต่เมื่อมันเกิดขึ้นการส่งออก CSV ที่ไม่เป็นไปตามข้อกำหนดหมายความว่านี่ไม่ใช่วิธีที่จะไป
flow2k

วิธีนี้แก้ไข^Mปัญหาสำหรับฉันในขณะที่คำแนะนำ 2 คำตอบที่ยอมรับไม่ได้
985366

55

ใน Python 3 (ฉันไม่ได้ลองใน Python 2) คุณสามารถทำได้ง่ายๆ

with open('output.csv','w',newline='') as f:
    writer=csv.writer(f)
    writer.writerow(mystuff)
    ...

ตามเอกสาร

เพิ่มเติมเกี่ยวกับเรื่องนี้ในเชิงอรรถของ doc :

หากไม่ได้ระบุ newline = '' ขึ้นบรรทัดใหม่ที่ฝังอยู่ภายในฟิลด์ที่ยกมาจะไม่ถูกตีความอย่างถูกต้องและบนแพลตฟอร์มที่ใช้ \ r \ n linendings เมื่อเขียนเพิ่ม \ r จะถูกเพิ่ม ควรปลอดภัยที่จะระบุ newline = '' เสมอเนื่องจากโมดูล csv ทำการจัดการบรรทัดใหม่ (สากล) ของตัวเอง


2
@ Yibo-Yang คุณประหยัดเวลาได้มาก
1man

4
GREAT ฉันยืนยันด้วยวิธีนี้ใน python 3.5
jef

เหตุใดจึงไม่เป็นพฤติกรรมเริ่มต้น
Marc Stober

6

คุณสามารถแนะนำ พารามิเตอร์ lineterminator = '\ n'ในคำสั่ง csv writer

import csv
delimiter='\t'
with open('tmp.csv', '+w', encoding='utf-8') as stream:
    writer = csv.writer(stream, delimiter=delimiter, quoting=csv.QUOTE_NONE, quotechar='',  lineterminator='\n')
    writer.writerow(['A1' , 'B1', 'C1'])
    writer.writerow(['A2' , 'B2', 'C2'])
    writer.writerow(['A3' , 'B3', 'C3'])

1
ด้วย Python 3.5.2 นี่เป็นสิ่งเดียวที่ใช้ได้ผลสำหรับฉัน (ฉันใช้แค่lineterminator='\n') โมดูล CSV \r\nดูเหมือนจะเป็นจุดเริ่มต้นของ ไม่มีชุดของการขัดแย้งที่จะopenมีผลกระทบใด ๆ
Tommy

5

ฉันไม่แน่ใจว่าทำไมมันเกิดขึ้น แต่เปลี่ยนโหมดไฟล์ของคุณจาก "w" เป็น "wb" แก้ไข ดูคำตอบของฉันที่ " วิธีการลบ ^ M " สำหรับรายละเอียดเพิ่มเติม


3

คุณต้องเพิ่ม attribute newline = "\ n" เพื่อเปิดฟังก์ชั่นเช่นนี้:

with open('file.csv','w',newline="\n") as out:
    csv_out = csv.writer(out, delimiter =';')

2

โปรดทราบว่าถ้าคุณใช้ DictWriter คุณจะมีบรรทัดใหม่จากฟังก์ชั่นเปิดและบรรทัดใหม่จากฟังก์ชั่น writerow คุณสามารถใช้ newline = '' ภายในฟังก์ชั่นเปิดเพื่อลบ newline พิเศษ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.