CSV dengan Python menambahkan carriage return tambahan, di Windows


232
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()

Ini menghasilkan file,, test.csvdengan tambahan \rdi setiap baris, seperti:

test.csv

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

bukannya yang diharapkan:

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

Mengapa ini terjadi, atau sebenarnya ini perilaku yang diinginkan?

catatan:

  • Perilaku ini dapat terjadi dengan Python 2 atau 3.

Jawaban:


311

Python 3:

  • Seperti yang dijelaskan oleh YiboYang , setnewline=''
with open('output.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    ...
  • Seperti dicatat dalam komentar oleh CoDEmanX , aturnewline='\n'
with open('output.csv', 'w', newline='\n', encoding='utf-8') as f:
    writer = csv.writer(f)
    ...

Python 2:

Di Windows, selalu buka file Anda dalam mode biner ( "rb"atau "wb"), sebelum meneruskannya ke csv.readeratau csv.writer.

Meskipun file tersebut adalah file teks, CSV dianggap format biner oleh perpustakaan yang terlibat, dengan \r\nmemisahkan catatan. Jika pemisah itu ditulis dalam mode teks, runtime Python menggantikan \ndengan \r\n, maka \r\r\ndiamati dalam file.

Lihat jawaban ini sebelumnya .


3
Ini bagus untuk ASCII tetapi akan mematikan encoding seperti UTF-8. Solusi Jason di bawah ini berhasil untuk saya.
Tom

66
Dalam Python 3, saya bisa memperbaikinya dengan menggunakan pilihan berikut untuk file objek: open(..., "w", newline="\n", encoding="utf-8"). newlinebisa juga berupa string kosong, hasil yang sama. "wb"tidak bekerja di Python 3, string dan antarmuka buffer tidak kompatibel.
CodeManX

Cara elegan menangani pengembalian gerbong ekstra
ForeverLearner

2
Tidak berfungsi di Python2, jadi jika Anda harus kompatibel dengan 2 dan 3, gunakan jawaban yang diberikan oleh @ jason-r-coombs:writer = csv.writer(f, lineterminator='\n')
yossiz74

4
Ini benar-benar memalukan bahwa API dasar, umum dan sederhana seperti itu tidak berfungsi seperti yang dipersyaratkan
SomethingSomething

248

Sementara @ john-machin memberikan jawaban yang baik, itu tidak selalu merupakan pendekatan terbaik. Misalnya, ini tidak berfungsi pada Python 3 kecuali jika Anda menyandikan semua input Anda ke penulis CSV. Juga, itu tidak mengatasi masalah jika skrip ingin menggunakan sys.stdout sebagai aliran.

Saya sarankan untuk mengatur atribut 'lineterminator' ketika membuat penulis:

import csv
import sys

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

Contoh itu akan bekerja pada Python 2 dan Python 3 dan tidak akan menghasilkan karakter baris baru yang tidak diinginkan. Perhatikan, bagaimanapun, bahwa itu dapat menghasilkan baris baru yang tidak diinginkan (menghilangkan karakter LF pada sistem operasi Unix).

Namun dalam kebanyakan kasus, saya percaya bahwa perilaku lebih disukai dan lebih alami daripada memperlakukan semua CSV sebagai format biner. Saya memberikan jawaban ini sebagai alternatif untuk pertimbangan Anda.


6
Ini jawaban terbaik menurut saya. Seperti itu menjadi masalah di Unix, bagaimana dengan memanggil sys.platform dan menghadapinya secara dinamis?
sovemp

4
Jawaban terbaik menurut saya juga, dan lineterminator = '\ n' berfungsi dengan baik.
eikonal

1
Bisakah Anda memberikan contoh masalah yang muncul jika Anda tidak "menyandikan semua masukan Anda ke penulis CSV"?
Stephen

WASPADALAH: menggunakan cara \rini tidak lagi lolos! Sepertinya ini adalah bug csvwriter, tetapi seperti berdiri, mengeluarkan CSV yang tidak sesuai berarti ini bukan cara yang harus dilakukan.
flow2k

Ini menyelesaikan ^Mmasalah bagi saya sementara 2 saran jawaban yang diterima tidak berfungsi.
user985366

55

Di Python 3 (saya belum mencoba ini di Python 2), Anda juga bisa melakukannya

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

sesuai dokumentasi .

Lebih lanjut tentang ini di catatan kaki doc :

Jika baris baru = '' tidak ditentukan, baris baru yang disematkan di dalam bidang yang dikutip tidak akan diartikan dengan benar, dan pada platform yang menggunakan \ r \ n linendings pada penulisan, tambahan \ r akan ditambahkan. Seharusnya selalu aman untuk menentukan newline = '', karena modul csv melakukan penanganan baris baru (universal) sendiri.


2
@ Yibo-Yang, Anda menghemat banyak waktu saya.
laki

4
BAGUS. Saya mengkonfirmasi cara ini dalam python 3.5
jef

Mengapa ini tidak menjadi perilaku default?
Marc Stober

6

Anda dapat memperkenalkan parameter lineterminator = '\ n' dalam perintah 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
Dengan Python 3.5.2, ini adalah satu-satunya hal yang bekerja untuk saya (well, saya hanya menggunakan lineterminator='\n'); modul CSV tampaknya merupakan asal dari \r\n. Tidak ada set argumen yang openberpengaruh.
Tommy

5

Saya tidak yakin persis mengapa itu terjadi, tetapi mengubah mode file Anda dari "w" ke "wb" memperbaikinya. Lihat jawaban saya untuk " cara menghapus ^ M " untuk lebih jelasnya.


3

Anda harus menambahkan atribut newline = "\ n" untuk membuka fungsi seperti ini:

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

2

Perhatikan bahwa jika Anda menggunakan DictWriter, Anda akan memiliki baris baru dari fungsi terbuka dan baris baru dari fungsi writerow. Anda dapat menggunakan newline = '' di dalam fungsi terbuka untuk menghapus baris baru tambahan.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.