CSV em Python adicionando um retorno de carro extra, no 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()

Ele gera um arquivo, test.csvcom um extra \ra cada linha, da seguinte forma:

test.csv

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

em vez do esperado:

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

Por que isso está acontecendo ou esse é realmente o comportamento desejado?

Nota:

  • Esse comportamento pode ocorrer com o Python 2 ou 3.

Respostas:


311

Python 3:

  • Conforme descrito por YiboYang , definanewline=''
with open('output.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    ...
  • Conforme observado nos comentários do CoDEmanX , definanewline='\n'
with open('output.csv', 'w', newline='\n', encoding='utf-8') as f:
    writer = csv.writer(f)
    ...

Python 2:

No Windows, abra sempre seus arquivos no modo binário ( "rb"ou "wb") antes de passá-los para csv.readerou csv.writer.

Embora o arquivo seja um arquivo de texto, o CSV é considerado um formato binário pelas bibliotecas envolvidas, com a \r\nseparação de registros. Se esse separador for gravado no modo de texto, o tempo de execução do Python substituirá o \ncom \r\n, daí o \r\r\nobservado no arquivo.

Veja esta resposta anterior .


3
Isso é bom para ASCII, mas mata a codificação como UTF-8. A solução de Jason abaixo funcionou para mim.
Tom

66
Em Python 3, eu era capaz de corrigi-lo usando as seguintes opções para o objeto de arquivo: open(..., "w", newline="\n", encoding="utf-8"). newlinetambém pode ser uma sequência em branco, o mesmo resultado. "wb"não funciona no Python 3, as strings e a interface do buffer são incompatíveis.
CodeManX

Maneira elegante de lidar com o retorno de carro extra
ForeverLearner

2
Não funciona no python2, por isso, se você precisa ser compatível com ambos 2 e 3, use a resposta dada por @ Jason-r-Coombs:writer = csv.writer(f, lineterminator='\n')
yossiz74

4
Esta é uma verdadeira vergonha que tal API básico, comum e simples não funciona conforme necessário
SomethingSomething

248

Enquanto @ john-machin dá uma boa resposta, nem sempre é a melhor abordagem. Por exemplo, ele não funciona no Python 3, a menos que você codifique todas as suas entradas no gravador de CSV. Além disso, ele não soluciona o problema se o script quiser usar o sys.stdout como o fluxo.

Em vez disso, sugiro definir o atributo 'lineterminator' ao criar o gravador:

import csv
import sys

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

Esse exemplo funcionará no Python 2 e Python 3 e não produzirá os caracteres de nova linha indesejados. Observe, no entanto, que ele pode produzir novas linhas indesejáveis ​​(omitindo o caractere LF nos sistemas operacionais Unix).

Na maioria dos casos, porém, acredito que o comportamento é preferível e mais natural do que tratar todo o CSV como um formato binário. Eu forneço esta resposta como uma alternativa para sua consideração.


6
Esta é a melhor resposta na minha opinião. Quanto a ser problemático no Unix, que tal chamar a plataforma sys. e lidar com ela dinamicamente?
sovemp

4
Melhor resposta na minha opinião também, e lineterminator = '\ n' funciona lindamente.
eikonal

1
Você pode dar um exemplo do problema que surgir se você "não codificar todas as suas entradas para o gravador de CSV"?
Stephen

CUIDADO: usar este meio \rnão é mais escapado! Parece que isso está ocorrendo csvwriter, mas, como está, a saída de CSV não conforme significa que esse não é o caminho a seguir.
flow2k

Isso resolveu o ^Mproblema para mim, enquanto as 2 sugestões da resposta aceita não funcionaram.
user985366 29/01

55

No Python 3 (eu não tentei isso no Python 2), você também pode simplesmente fazer

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

conforme documentação .

Mais sobre isso na nota de rodapé do documento :

Se newline = '' não for especificado, as novas linhas incorporadas nos campos entre aspas não serão interpretadas corretamente e nas plataformas que usam \ r \ n linendings na gravação, um extra \ r será adicionado. Sempre deve ser seguro especificar newline = '', pois o módulo csv faz seu próprio tratamento (universal) de nova linha.


2
@ Yibo-Yang, você me salvou muito tempo.
1Man

4
ÓTIMO. Eu confirmei desta maneira em python 3.5
jef 26/09/16

Por que esse não seria o comportamento padrão?
Marc Stober

6

Você pode introduzir o parâmetro lineterminator = '\ n' no comando 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
Com o Python 3.5.2, essa foi a única coisa que funcionou para mim (bem, eu usei apenas lineterminator='\n'); o módulo CSV parecia ser a origem de \r\n. Nenhum conjunto de argumentos openteve qualquer efeito.
Tommy

5

Não sei exatamente por que isso está acontecendo, mas alterar o modo de arquivo de "w" para "wb" o corrige. Veja minha resposta para " como remover ^ M " para mais detalhes.


3

Você precisa adicionar o atributo newline = "\ n" para abrir uma função como esta:

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

2

Observe que, se você usar o DictWriter, terá uma nova linha da função aberta e uma nova linha da função de gravação. Você pode usar newline = '' na função aberta para remover a nova linha extra.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.