2016-08-04 30 views
1

In Python 2 dieser Code ist, was würde ich erwarten:Python 3 csv.writer prints "Bytes" mit dem Präfix und zitiert

import csv 
import sys 

writer = csv.writer(sys.stdout) 
writer.writerow([u'hello', b'world']) 

Er druckt:

hello,world 

Aber in Python 3, bytes werden mit einem Präfix gedruckt und zitiert:

hello,b'world' 

da CSV ein generisches Datenaustauschformat ist, und da kein anderes System Als Python weiß, was b'' ist, muss ich dieses Verhalten deaktivieren. Aber ich habe nicht herausgefunden, wie.

Natürlich könnte ich zuerst str.decode auf allen bytes verwenden, aber das ist unbequem und ineffizient. Was ich wirklich will, ist entweder die Literal Bytes in die Datei zu schreiben, oder eine Codierung (z. B. 'ASCII') an csv.writer() übergeben, so dass es weiß, wie bytes Objekte, die es sieht, zu dekodieren.

Antwort

0

Ich glaube nicht, dass es eine Möglichkeit gibt zu vermeiden, dass die Byte-Strings explizit in Unicode-Strings mit dem csv Modul in Python 3 konvertiert werden müssen. In Python 2 werden sie implizit in ASCII konvertiert.

Um dies zu vereinfachen, können Sie die Objekte csv.writer (oder Wrap) wie unten gezeigt effektiv ableiten, was den Prozess komfortabler macht.

import csv 

class MyCsvWriter(object): 
    def __init__(self, *args, **kwrds): 
     self.csv_writer = csv.writer(*args, **kwrds) 

    def __getattr__(self, name): 
     return getattr(self.csv_writer, name) 

    def writerow(self, row): 
     self.csv_writer.writerow(
      str(v, encoding='utf-8') if isinstance(v, bytes) else v for v in row) 

    def writerows(self, rows): 
     for row in rows: 
      self.writerow(row) 

with open('bytes_test.csv', 'w', newline='') as file: 
    writer = MyCsvWriter(file) 
    writer.writerow([u'hello', b'world']) 
+0

Bytes Strings und Unicode Strings sind zwei verschiedene Arten in Python 2. Python 2 erlaubt nur die implizite Konvertierung mit dem Standard-Ascii-Codec. –

+0

@Mark: Danke ... Antwort aktualisiert entsprechend. – martineau

0

csv schreibt Textdateien, und erwartet, dass Unicode (Text) Strings in Python 3.

csv binäre Dateien schreibt und erwartet Byte-Strings in Python 2, aber implizite Kodierung von Unicode-Strings auf Byte-Strings erlaubt die Verwendung von Standard ascii Codec. Python 3 erlaubt keine implizite Konvertierung, so dass Sie es nicht wirklich vermeiden können:

#!python3 
import csv 
import sys 
writer = csv.writer(sys.stdout) 
writer.writerow(['hello', b'world'.decode()])