Ecrire sur un fichier CSV en langage python

Fermé
Frankk - 20 avril 2011 à 16:34
heyquem Messages postés 759 Date d'inscription mercredi 17 juin 2009 Statut Membre Dernière intervention 29 décembre 2013 - 22 avril 2011 à 01:53
Bonjour,

Je cherche depuis quelque temps comment écrire sur un fichier csv avec python. J'ai utilisé les lignes données ici : http://www.commentcamarche.net/faq/2382-python-lire-et-ecrire-des-fichiers-csv
Mais python m'affiche ce message d'erreur : can't write str to binary stream

Auriez-vous d'autres commandes ?
Merci d'avance !

A voir également:

3 réponses

heyquem Messages postés 759 Date d'inscription mercredi 17 juin 2009 Statut Membre Dernière intervention 29 décembre 2013 131
Modifié par heyquem le 23/04/2011 à 03:30
Beaucoup de choses ont changé de Python 2 à Python 3.



1) L'une est particulièrement importante.

En Python 2, les chaînes sont en fait des chaînes d'éléments de nature double puisqu'elles peuvent être traitées comme des chaînes de caractères (càd interprétées) ou comme des chaînes de bytes bruts, selon la nature du traitement.
Le type str tel que défini dans Python 2 recouvre en fait des objets de nature trop large, avec trop de méthodes.

Désormais en Python 3, les chaînes de caractères et les séquences de données binaires sont deux choses bien distinctes.

Les premières sont représentées physiquement par des objets pour le type desquels a été conservé le nom str mais dont la sémantique est celle de l'ancien Unicode de Python 2 , puisqu'en Python 3 toutes les chaînes de caractères sont exclusivement en Unicode.
Les secondes sont représentées par des objets conteneurs de bytes bruts ayant le nouveau type bytes.

Ceci signifie que les chaînes de caractères ne sont plus automatiquement traitées comme des chaînes de bytes bruts comme dans les cas où cela avait lieu en fonction du contexte, en Python 2.
C'est ce traitement versatile des chaînes en Python 2, et ses inconvénients, qui a constitué la motivation de la création du type bytes :

Python's current string objects are overloaded. They serve to hold
both sequences of characters and sequences of bytes. This
overloading of purpose leads to confusion and bugs. In future
versions of Python, string objects will be used for holding
character data. The bytes object will fulfil the role of a byte
container. Eventually the unicode type will be renamed to str
and the old str type will be removed.

https://www.python.org/dev/peps/pep-0358/

La PEP 358 décrit l'introduction du nouveau type bytes qui fut planifiée pour les versions 2.6 et 3.0. Elle date de février 2006. La version la plus récente disponible à ce moment-là était Python 2.4.2.
L'extrait ci-dessus décrit donc l'ambivalence du traitement des chaînes qui a existé pour toutes les versions Python 2, jusqu'à Python 2.7 puisque ce n'est qu'à partir de Python 3 que les chaînes de caractères sont exclusivement du type str redéfini, c'est à dire ne comportant plus que les méthodes des chaînes de caractères en Unicode.




2) En Python 2, les chaînes écrites/lues dans un fichier ne posent pas de problème de conformité avec un type précis, tant qu'il ne s'agit pas de chaînes de type unicode , puisqu'il n'y a pour ces chaînes qu'un seul type str , et qu'il y a une prise en charge de ces chaînes qui est automatiquement effectuée en fonction du mode d'ouverture spécifié pour le fichier.
C'est à dire que pour un fichier ouvert en mode non binaire, une chaîne écrite/lue est prise en charge comme une chaîne de caractères et que pour un fichier ouvert en mode binaire, la même chaîne écrite/lue est prise en charge comme une chaîne de bytes bruts.

Pour des entrées/sorties de chaînes Unicode en Python 2, il faut ouvrir un fichier au moyen de la fonction open()du module codecs. Les fonctions de ce module forment une interface d'encodage/décodage bas-niveau qui permet d'effectuer les opérations de réception et de stockage/transmission de données en Unicode. La fonction codecs.open() retourne un handler de fichier, toujours en mode binaire, au travers duquel les opérations de lecture et écriture par les méthodes read() et write() des chaînes Unicode en output/input se font en prenant comme controleur des encodages/décodages l'encoding attribué au fichier lors de son ouverture.
Mais ceci est une autre histoire.

La fonction codecs.open() retourne un fichier toujours ouvert en mode binaire, même si ce n'est pas spécifié dans le code:

« Files are always opened in binary mode, even if no binary mode was specified. This is done to avoid data loss due to encodings using 8-bit values. This means that no automatic conversion of '\n' is done on reading and writing. »
http://docs.python.org/library/codecs.html#module-codecs

Cette remarque atteste qu'avec la fonction open()built-in , la seule différence de traitement des chaînes en input/output entre un fichier ouvert en mode standard et un fichier ouvert en mode binaire ne se manifeste en réalité qu'au niveau des newlines. Il n'y a qu'une différence minime entre les chaînes de caractères et les chaînes de bytes bruts en Python 2 et cette différence n'est pas dans leur nature mais dans les traitements qui leur sont appliqués.

Il s'ensuit de ces caractéristiques qu'en Python 2 on ne prend pas l'habitude de se soucier de la nature des chaînes non Unicode en input/output, seulement du mode d'ouverture des fichiers quand l'exactitude des décompte des newlines importe (car Python fait par ailleurs des manipulations de ces newlines en douce par en dessous quand le fichier est ouvert en mode non binaire, cf la PEP 278 portant sur le Newline Universal Support).



Aussi bien en Python 2 que 3, il est possible d'ouvrir les fichiers CSV en mode binaire ou non binaire.

Mais pour certaines plateformes (Windows), il est conseillé de les ouvrir en mode binaire en Python 2:

csv.reader(csvfile[, dialect='excel'][, fmtparam])
csv.writer(csvfile[, dialect='excel'][, fmtparam])
If csvfile is a file object, it must be opened with the 'b' flag on platforms where that makes a difference.
https://docs.python.org/3/library/csv.html#module-csv

Pour Python 3, cette injonction est remplacée par celle d'utiliser un paramètre défini avec un argument par défaut, uniquement pour csv.reader() :

csv.reader() :
csv.reader(csvfile, dialect='excel', **fmtparams)
If csvfile is a file object, it should be opened with newline=''.

https://docs.python.org/release/3.1/library/csv.html#module-csv



* En définitive, ffrank, je suppose que tu utilises Python 3 après avoir pratiqué Python 2, que tu as ouvert plus ou moins par habitude un fichier CSV en mode binaire et que tu as essayé d'y écrire une chaîne de type str

Or lorsqu'on veut faire de entrées/sorties d'un fichier en Python 3, il faut que les chaînes à écrire ou lire soit du type compatible avec le mode d'ouverture du fichier: str pour un mode non binaire, bytes pour un mode binaire.

Si tu veux écrire dans un fichier CSV ouvert en mode binaire, il faut donc que tu lui passes des chaînes de bytes bruts obtenues:

- soit par une définition du genre b'voici une séquence de bytes' , avec b'....'

- soit par l'action de la fonction encode() sur une chaîne de caractères.
Là encore, il est intéressant de comparer les descriptifs de cette fonction dans la doc de Python 2:
str.encode([encoding[, errors]])
Return an encoded version of the string.

et dans la doc de Python 3
str.encode([encoding[, errors]])
Return an encoded version of the string as a bytes object.


La fonction encode() en Python 3 ne sert plus à transformer des chaînes Unicode en chaînes de l'ancien type str, elle sert à transformer une chaîne de type str en une chaîne de type bytes.
1
heyquem Messages postés 759 Date d'inscription mercredi 17 juin 2009 Statut Membre Dernière intervention 29 décembre 2013 131
20 avril 2011 à 19:50
Bonjour,

Tu utilises Python 3 ?
0
Oui
0