J'essaie d'utiliser le module CSV pour lire un fichier CSV UTF-8, et j'ai des problèmes pour créer un code générique pour Python 2 et 3 en raison de l'encodage.
Voici le code d'origine en python 2.7: P>
with codecs.open(filename, 'r', encoding='utf-8') as csvfile: csv_reader = csv.reader(csvfile, quotechar='\"') langs = next(csv_reader)[1:] for row in csv_reader: pass
3 Réponses :
En effet, en Python 2, le fichier doit être ouvert en mode binaire, mais en mode Python 3 en mode texte. également dans Python 3 newline = '' code> devrait être spécifié
(que vous avez oublié).
Vous devrez faire l'ouverture du fichier dans un bloc IF. P>
import sys if sys.version_info[0] < 3: infile = open(filename, 'rb') else: infile = open(filename, 'r', newline='', encoding='utf8') with infile as csvfile: ...
Pouvez-vous faire avec code> sur une poignée de fichier?
@Tim: Ce n'est pas une poignée de fichier, c'est un objet de fichier et vous pouvez faire avec code> sur des objets de fichier. C'est exactement ce que vous faites lorsque vous faites
avec ouvert (... code>.
Logique. Vous ne le voyez jamais vraiment comme ça, c'est toujours avec Open (...) code> dans les docs, mais de cette façon n'est pas à moitié mauvais - vous permet d'envelopper le
ouvert () Code> dans un
ESSAYEZ CODE> Bloc et Catch> Fichier non trouvé Code> etc. Avant de le remettre sur le bloc code>.
Ou, dans certaines situations, si sys.version <'3': Open = codecs.open code>.
@Agf: Ouais, cela peut travailler aussi. Codecs.Open et Python 3 Open ne sont pas exactement les mêmes, cependant, il y a donc des pièges subtils, mais cela fonctionnera souvent. En 2.6 et 2.7, vous pouvez faire à partir d'IO importer Ouvrir code>, cependant.
Le lecteur Python 2 CSV fonctionne uniquement avec ASCII, il suffit donc d'utiliser «R» ou «RB» à ouvrir uniquement une partie de la question.
Est-ce toujours la bonne approche, même avec six ou 2to3 et d'autres bibliothèques? Je viens de voir quel âge a cette réponse.
Pour autant que je sache, oui.
Vieille question que je connais, mais je cherchais à faire ça. Juste au cas où quelqu'un vient sur ceci et pourrait le trouver utile.
C'est comme ça que j'ai résolu la mienne, merci Lennart Regèbre pour le conseil. : p> puis faites ce que vous devez faire: p>
Le code ci-dessous définit une fonction Voici les deux variantes pour csv_rows () code> qui renvoie le contenu d'un fichier comme séquence de listes. Exemple d'utilisation: p>
csv_rows () code>: un pour Python 3+ et un autre pour Python 2.6+. Pendant l'exécution, il choisit automatiquement la variante appropriée.
utf8Recoder code> et
Unicodereader code> sont des copies verbatim du Exemples de la documentation de la bibliothèque Python 2.7 . P>
import csv
import io
import sys
if sys.version_info[0] >= 3:
# Python 3 variant.
def csv_rows(csv_path, encoding, **keywords):
with io.open(csv_path, 'r', newline='', encoding=encoding) as csv_file:
for row in csv.reader(csv_file, **keywords):
yield row
else:
# Python 2 variant.
import codecs
class UTF8Recoder:
"""
Iterator that reads an encoded stream and reencodes the input to UTF-8
"""
def __init__(self, f, encoding):
self.reader = codecs.getreader(encoding)(f)
def __iter__(self):
return self
def next(self):
return self.reader.next().encode("utf-8")
class UnicodeReader:
"""
A CSV reader which will iterate over lines in the CSV file "f",
which is encoded in the given encoding.
"""
def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
f = UTF8Recoder(f, encoding)
self.reader = csv.reader(f, dialect=dialect, **kwds)
def next(self):
row = self.reader.next()
return [unicode(s, "utf-8") for s in row]
def __iter__(self):
return self
def csv_rows(csv_path, encoding, **kwds):
with io.open(csv_path, 'rb') as csv_file:
for row in UnicodeReader(csv_file, encoding=encoding, **kwds):
yield row
Donc, vous voulez que le code fonctionne inchangé à la fois sur Python 2.7 et 3? Probablement impossible, étant donné que tellement changé avec la manipulation des cordes, etc.
Est-il possible de spécifier le code de bloc pour Python 2 ou 3?
Vous pouvez vérifier
sys.version code> et envelopper un
si - else code> instruction autour de votre code, oui.
@Tim Pietzchker; Il est préférable de demander pardon que la permission.
Je pense que vous aviez le drapeau B dans le mauvais exemple, je l'ai changé.
@Jakobbowyer EAFP ne fonctionne que dans des fonctions nommées, pas dans les expressions génératrices. Ceci est intentionnel, que je peux dire parce que PEP 463 pour attraper en ligne était rejeté.
Alors que la recommandation "officielle" est de faire des CSV différemment dans Python 2 et Python 3, il y a un Nettoyant, plus élégant répertorié comme une réponse à un Similaire, Si ce n'est pas dupliquer, question .