Le fichier CSV écrit avec Python a des lignes vides entre chaque ligne

446
import csv

with open('thefile.csv', 'rb') as f:
  data = list(csv.reader(f))
  import collections
  counter = collections.defaultdict(int)

  for row in data:
        counter[row[10]] += 1


with open('/pythonwork/thefile_subset11.csv', 'w') as outfile:
    writer = csv.writer(outfile)
    for row in data:
        if counter[row[10]] >= 504:
           writer.writerow(row)

Ce code lit thefile.csv, modifie et écrit les résultats dans thefile_subset1.

Cependant, lorsque j'ouvre le fichier CSV résultant dans Microsoft Excel, il y a une ligne vierge supplémentaire après chaque enregistrement!

Existe-t-il un moyen de ne pas mettre une ligne vierge supplémentaire?

l --''''''---------------- '' '' '' '' '' '' '
la source
4
Veuillez confirmer que cela se produit lorsque vous exécutez ce code sous Windows
John Machin
Voir la réponse sur ce fil: stackoverflow.com/questions/3348460/…
Febin Mathew

Réponses:

887

En Python 2, ouvrez outfileavec mode 'wb'au lieu de 'w'. Les csv.writerécrit \r\ndans le fichier directement. Si vous n'ouvrez pas le fichier en mode binaire , il écrira \r\r\ncar sous Windows le mode texte se traduira chacun \nen \r\n.

Dans Python 3, la syntaxe requise a changé (voir les liens de documentation ci-dessous), alors ouvrez-le outfileavec le paramètre supplémentaire newline=''(chaîne vide) à la place.

Exemples:

# Python 2
with open('/pythonwork/thefile_subset11.csv', 'wb') as outfile:
    writer = csv.writer(outfile)

# Python 3
with open('/pythonwork/thefile_subset11.csv', 'w', newline='') as outfile:
    writer = csv.writer(outfile)

Liens de documentation

Mark Tolonen
la source
1
Quoi qu'il en soit, la réponse de @Mark Tolonen a résolu de nombreuses questions liées aux lignes supplémentaires ajoutées lors de l'enregistrement d'un fichier texte standard (aucun csv utilisé).
dlewin
1
Pour la compatibilité entre 2.6 / 2.7 et 3, vous pouvez utiliser io.openavec l' newlinesargument. Si vous écrivez toujours en 2.x, cela semble de toute façon un meilleur choix car il est compatible avec le futur.
jpmc26
@ jpmc26 Normalement, c'est un bon conseil, mais le module csv ne fonctionne pas correctement avec io.open. Il existe un unicodecsvmodule tiers pour Python 2.7 qui fonctionne mieux.
Mark Tolonen
Une idée pourquoi l' newline=''astuce ne fonctionne pas en python3 avec StringIO ou TemporaryFile?
fmoo
@fmoo définit "ne fonctionne pas". Ils travaillent tous les deux comme je l'attends. StringIOmet en mémoire tampon les mêmes points de code qui seraient encodés dans un fichier et TemporaryFileprend en charge le newlineparamètre, afin qu'il puisse être ouvert comme avec open. Posez une question avec un exemple de programme qui ne fonctionne pas.
Mark Tolonen
65

L'ouverture du fichier en mode binaire "wb" ne fonctionnera pas dans Python 3+. Ou plutôt, vous devez convertir vos données en binaire avant de les écrire. C'est juste un problème.

Au lieu de cela, vous devez le conserver en mode texte, mais remplacer la nouvelle ligne comme vide. Ainsi:

with open('/pythonwork/thefile_subset11.csv', 'w', newline='') as outfile:
David Maddox
la source
13

La réponse simple est que les fichiers csv doivent toujours être ouverts en mode binaire que ce soit pour l'entrée ou la sortie, car sinon sous Windows il y a des problèmes avec la fin de la ligne. Spécifiquement en sortie, le module csv écrira \r\n(le terminateur de ligne CSV standard) puis (en mode texte) le runtime remplacera le \npar \r\n(le terminateur de ligne standard Windows) donnant un résultat de \r\r\n.

Jouer avec le lineterminatorn'est PAS la solution.

John Machin
la source
Quelle est cette «norme» CSV dont vous parlez?
Dan Breslau
3
@Dan: J'ai utilisé "standard" comme adjectif, pas un nom, signifiant "habituel" ou "banal". Si vous voulez une approximation d'une norme (nom), lisez tools.ietf.org/html/rfc4180
John Machin
1
Le point est (comme vous le laissez entendre) qu'il n'y a pas de norme. Cette RFE est informative. Bien que \ r \ n puisse être "standard" sous Windows, je suis sûr que les applications Unix ne le voient généralement pas de cette façon.
Dan Breslau
2
@Dan: C'est exact - il n'y a pas de norme. Les scripts doivent spécifier le lineterminator [aurait dû être nommé ROWterminator] qu'ils souhaitent (sinon la valeur par défaut) et continuer à utiliser le mode binaire dans le cas où le script est exécuté sur Windows, sinon le "lineterminator" risque d'être bourré.
John Machin
8

Remarque: Il semble que ce ne soit pas la solution préférée en raison de la façon dont la ligne supplémentaire a été ajoutée sur un système Windows. Comme indiqué dans le document python :

Si csvfile est un objet fichier, il doit être ouvert avec l'indicateur «b» sur les plates-formes où cela fait une différence.

Windows est l'une de ces plateformes où cela fait une différence. Bien que la modification du terminateur de ligne comme je l'ai décrit ci-dessous puisse avoir résolu le problème, le problème pourrait être évité complètement en ouvrant le fichier en mode binaire. On pourrait dire que cette solution est plus "élégante". "Jouer" avec le terminateur de ligne aurait probablement entraîné un code non transférable entre les systèmes dans ce cas, où l'ouverture d'un fichier en mode binaire sur un système Unix n'a aucun effet. c'est à dire. il en résulte un code compatible entre les systèmes.

Depuis Python Docs :

Sous Windows, «b» ajouté au mode ouvre le fichier en mode binaire, il existe donc également des modes comme «rb», «wb» et «r + b». Python sur Windows fait une distinction entre les fichiers texte et binaires; les caractères de fin de ligne des fichiers texte sont automatiquement légèrement modifiés lors de la lecture ou de l'écriture des données. Cette modification en arrière-plan des données de fichier convient aux fichiers texte ASCII, mais elle corrompra les données binaires comme celles des fichiers JPEG ou EXE. Faites très attention à utiliser le mode binaire lors de la lecture et de l'écriture de tels fichiers. Sous Unix, cela ne fait pas de mal d'ajouter un «b» au mode, vous pouvez donc l'utiliser indépendamment de la plate-forme pour tous les fichiers binaires.

Original :

Dans le cadre des paramètres facultatifs pour le csv.writer si vous obtenez des lignes vierges supplémentaires, vous devrez peut-être changer le lineterminator (info ici ). Exemple ci-dessous adapté des documents csv de la page python . Changez-le de '\ n' en ce qu'il devrait être. Comme ce n'est qu'un coup de couteau dans le noir, le problème peut ou non fonctionner, mais c'est ma meilleure estimation.

>>> import csv
>>> spamWriter = csv.writer(open('eggs.csv', 'w'), lineterminator='\n')
>>> spamWriter.writerow(['Spam'] * 5 + ['Baked Beans'])
>>> spamWriter.writerow(['Spam', 'Lovely Spam', 'Wonderful Spam'])
Derek Litz
la source
J'étais sur le point de poster à ce sujet - lineterminator = '\ n' a fonctionné pour moi dans un test simple.
Dan Breslau
puis-je faire cela> ?? avec open ('/ pythonwork / thefile_subset11.csv', 'w'), lineterminator = '\ n' comme outfile:
l --''''''--------- '' '' '' '' '' '' '27
1
@I__: Vous devriez vraiment commencer à parcourir les documents Python. Derek vous a donné le lien: docs.python.org/library/csv.html
Dan Breslau
5

J'écris cette réponse par écrit en python 3, car j'ai initialement rencontré le même problème.

J'étais censé obtenir des données d'Arduino en les utilisant PySerialet les écrire dans un fichier .csv. Chaque lecture dans mon cas se terminait par '\r\n', donc la nouvelle ligne séparait toujours chaque ligne.

Dans mon cas, l' newline=''option n'a pas fonctionné. Parce qu'il a montré une erreur comme:

with open('op.csv', 'a',newline=' ') as csv_file:

ValueError: illegal newline value: ''

Il semble donc qu'ils n'acceptent pas l'omission de la nouvelle ligne ici.

Ne voyant qu'une des réponses ici, j'ai mentionné le terminateur de ligne dans l'objet écrivain, comme,

writer = csv.writer(csv_file, delimiter=' ',lineterminator='\r')

et cela a fonctionné pour moi pour sauter les nouvelles lignes supplémentaires.

Debanjan Dey
la source
2
Ceci est une erreur. with open('my_file.csv', 'a',newline='') as csvfile: fonctionne très bien. Le problème avec votre réponse est qu'ici vous écrivez ' 'au lieu de''
Nasrin
2
with open(destPath+'\\'+csvXML, 'a+') as csvFile:
    writer = csv.writer(csvFile, delimiter=';', lineterminator='\r')
    writer.writerows(xmlList)

Le "lineterminator = '\ r'" permet de passer à la ligne suivante, sans ligne vide entre deux.

SheRa
la source
1

Empruntant à cette réponse , il semble que la solution la plus propre soit à utiliser io.TextIOWrapper. J'ai réussi à résoudre ce problème par moi-même comme suit:

from io import TextIOWrapper

...

with open(filename, 'wb') as csvfile, TextIOWrapper(csvfile, encoding='utf-8', newline='') as wrapper:
    csvwriter = csv.writer(wrapper)
    for data_row in data:
        csvwriter.writerow(data_row)

La réponse ci-dessus n'est pas compatible avec Python 2. Pour avoir la compatibilité, je suppose qu'il faudrait simplement envelopper toute la logique d'écriture dans un ifbloc:

if sys.version_info < (3,):
    # Python 2 way of handling CSVs
else:
    # The above logic
fantôme-99w
la source
0

Utilisez la méthode définie ci-dessous pour écrire des données dans le fichier CSV.

open('outputFile.csv', 'a',newline='')

Ajoutez simplement un newline=''paramètre supplémentaire dans la openméthode:

def writePhoneSpecsToCSV():
    rowData=["field1", "field2"]
    with open('outputFile.csv', 'a',newline='') as csv_file:
        writer = csv.writer(csv_file)
        writer.writerow(rowData)

Cela va écrire des lignes CSV sans créer de lignes supplémentaires!

Febin Mathew
la source
-1

Lors de l'utilisation de Python 3, les lignes vides peuvent être évitées en utilisant le module codecs . Comme indiqué dans la documentation, les fichiers sont ouverts en mode binaire donc aucune modification du kwarg de nouvelle ligne n'est nécessaire. Je rencontrais récemment le même problème et cela a fonctionné pour moi:

with codecs.open( csv_file,  mode='w', encoding='utf-8') as out_csv:
     csv_out_file = csv.DictWriter(out_csv)
JBa
la source