352 votes

CSV en Python : ajout d'un retour chariot supplémentaire, sous Windows

import csv

with open('test.csv', 'w') as outfile:
    writer = csv.writer(outfile, delimiter=',', quoting=csv.QUOTE_MINIMAL)
    writer.writerow(['hi', 'dude'])
    writer.writerow(['hi2', 'dude2'])

Le code ci-dessus génère un fichier, test.csv avec un supplément \r à chaque rangée, comme ceci :

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

au lieu de l'attendu

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

Pourquoi cela se produit-il, ou est-ce vraiment le comportement souhaité ?

1 votes

512voto

John Machin Points 39706

Python 3 :

L'officiel csv documentation recommande open le fichier avec newline='' sur toutes les plateformes pour Désactiver la traduction universelle des nouvelles lignes :

with open('output.csv', 'w', newline='', encoding='utf-8') as f:
    writer = csv.writer(f)
    ...

Le rédacteur du CSV termine chaque ligne par le symbole lineterminator du dialecte qui est '\r\n' pour l'option par défaut excel dialecte sur toutes les plateformes parce que c'est ce qui RFC 4180 recommande.


Python 2 :

Sous Windows, ouvrez toujours vos fichiers en mode binaire ( "rb" o "wb" ), avant de les transmettre à csv.reader o csv.writer .

Bien que le fichier soit un fichier texte, CSV est considéré comme une binaire par les bibliothèques concernées, avec \r\n séparant les enregistrements. Si ce séparateur est écrit en mode texte, le moteur d'exécution de Python remplace la balise \n con \r\n d'où le \r\r\n observé dans le dossier.

Voir cette réponse précédente .

0 votes

Lorsque j'utilise le code ci-dessus, j'obtiens seulement \r les nouvelles lignes, il n'y a pas de \n...

284voto

Jason R. Coombs Points 11130

Alors que @john-machin donne une bonne réponse, ce n'est pas toujours la meilleure approche. Par exemple, elle ne fonctionne pas sur Python 3, à moins que vous ne codiez toutes vos entrées vers le rédacteur CSV. De même, elle ne résout pas le problème si le script veut utiliser sys.stdout comme flux.

Je suggère plutôt de définir l'attribut 'lineterminator' lors de la création du rédacteur :

import csv
import sys

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

Cet exemple fonctionnera sur Python 2 et Python 3 et ne produira pas les caractères de nouvelle ligne indésirables. Notez, cependant, qu'il peut produire des nouvelles lignes indésirables (en omettant le caractère LF sur les systèmes d'exploitation Unix).

Dans la plupart des cas, cependant, je pense que ce comportement est préférable et plus naturel que de traiter tous les CSV comme un format binaire. Je fournis cette réponse comme une alternative pour votre considération.

4 votes

Pouvez-vous donner un exemple du problème qui se pose si vous ne "codez pas toutes vos entrées au rédacteur CSV" ?

3 votes

ATTENTION : en utilisant ce moyen \r n'est plus échappé ! Il semble que ce soit un bogue dans csvwriter mais dans l'état actuel des choses, la sortie d'un CSV non conforme signifie que c'est pas la voie à suivre.

0 votes

Cela a permis de résoudre le problème ^M pour moi, alors que les deux suggestions de la réponse acceptée n'ont pas fonctionné.

67voto

Yibo Yang Points 420

En Python 3 (je n'ai pas essayé en Python 2), vous pouvez aussi simplement faire

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

selon documentation .

Plus d'informations à ce sujet dans la documentation note de bas de page :

Si newline='' n'est pas spécifié, les nouvelles lignes incorporées dans les champs entre guillemets ne seront pas interprétées correctement, et sur les plates-formes qui utilisent la fonction \r\n linendings sur écrire un supplément \r sera ajouté. Il devrait toujours être sûr de spécifier newline='', puisque le module csv fait sa propre gestion des gestion (universelle) des nouvelles lignes.

1 votes

Pourquoi cela ne serait-il pas le comportement par défaut ?

2 votes

@MarcStober parce que pour la majorité des fichiers ouverts, vous voulez que les nouvelles lignes soient traduites au niveau de la plateforme par défaut. Vous ne voulez jamais mettre newline='' lorsque vous avez besoin d'un contrôle total sur la façon dont les terminaisons de ligne sont traitées. Par exemple, lorsque vous écrivez des données CSV qui sont conformes à la RFC. Notez que c'est pas le CSV qui ouvre le fichier ici .

14voto

Wesam Na Points 881

Vous pouvez introduire le lineterminator=' \n ' dans la commande 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'])

4 votes

Avec Python 3.5.2, c'est la seule chose qui a fonctionné pour moi (enfin, j'ai utilisé seulement lineterminator='\n' ) ; le module CSV semblait être à l'origine de \r\n . Aucun ensemble d'arguments pour open n'a eu aucun effet.

4voto

Ned Batchelder Points 128913

Je ne sais pas exactement pourquoi cela se produit, mais changer votre mode de fichier de "w" à "wb" le résout. Voir ma réponse à la question " comment supprimer ^M "pour plus de détails.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X