2015-04-24 3 views
11

EDIT: Ich habe es in den Titel, aber nur festgestellt, dass ich es nicht im Körper erwähnt. Dies scheint spezifisch für Windows zu sein.Eine .CSV-Datei in Python schreiben, die sowohl für Python 2.7+ und Python 3.3+ in Windows funktioniert

Ich habe eine harte Zeit schreiben Ausgabe mit dem csv Python-Modul in einem Skript, das mit Python 2.7 und 3.3 funktioniert.

Erster Versuch, die in Python 2.7 wie erwartet funktioniert:

with open('test.csv', 'wb') as csv_file: 
    writer = csv.DictWriter(csv_file, ['header1', 'header2']) 
    writer.writeheader() 
    for item in items: 
     writer.writerow(item) 

Wenn jedoch die gleiche Sache in Python ausgeführt wird 3.3 Sie aufzuwickeln mit:

TypeError: 'str' does not support the buffer interface 

So 'wb'-'wt' ich ändern und es läuft, aber jetzt habe ich eine extra leere Zeile jede zweite Zeile in der Datei.

dass zu beheben, ich ändern:

with open('test.csv', 'wt') as csv_file: 

zu:

with open('test.csv', 'wt', newline='') as csv_file: 

Aber jetzt bricht es Python 2.7:

TypeError: 'newline' is an invalid keyword argument for this function 

Ich weiß, ich könnte nur etwas tun, wie :

try: 
    with open('test.csv', 'wt', newline='') as csv_file: 
     writer = csv.DictWriter(csv_file, ['header1', 'header2']) 
     writer.writeheader() 
     for item in items: 
      writer.writerow(item) 
except TypeError: 
    with open('test.csv', 'wb') as csv_file: 
     writer = csv.DictWriter(csv_file, ['header1', 'header2']) 
     writer.writeheader() 
     for item in items: 
      writer.writerow(item) 

Allerdings hat das einige ernsthaft schlechte Duplizierung.

Hat jemand eine sauberere Art, dies zu tun?

EDIT: Die Testdaten ist einfach und hat keine Zeilenumbrüche oder irgendetwas:

items = [{'header1': 'value', 'header2': 'value2'}, 
     {'header1': 'blah1', 'header2': 'blah2'}] 
+0

Kannst du '' w'' nicht anstelle von '' wb'' oder '' wt'' verwenden? – nathancahill

+0

Sind die Strings in Ihrer Items-Liste Unicode-Strings, wenn Sie das Skript in Python 2 ausführen? Sind die Werte immer ASCII oder könnten sie zusätzliche Zeichen enthalten, die codiert werden müssen? Selbst wenn Sie in beiden Versionen von Python denselben Code ausführen können, erhalten Sie möglicherweise nicht die gleichen Ergebnisse! – Blckknght

+0

@Blckknght - Ich habe die Testdaten am Ende der Frage hinzugefügt. Es ist nur ASCII-Text. – Tamerz

Antwort

6

Ich habe ein paar Möglichkeiten ausprobiert. Soweit ich einfach sehen kann, könnte 'w' mit einer Lösung sein:

with open('test.csv', 'w') as csv_file: 
    writer = csv.DictWriter(csv_file, fieldnames=['header1', 'header2'], lineterminator='\n') 
    # write something 
+1

Wenn ich das tue, bekomme ich immer noch alle zwei Zeilen Leerzeilen. Hast du das in Windows oder auf etwas anderem versucht? – Tamerz

+0

@Tamerz Sie erhalten zusätzliche neue Zeilen, weil Sie zusätzliche neue Zeilen in Ihren Daten haben ... '.strip()' könnte sein, was Sie brauchen. – gboffi

+0

@Tamerz Ich versuchte mit einigen gefälschten Daten und es stellte sich heraus, gut. Ich denke also, dass auch mit Ihren Daten etwas nicht stimmt. – skyline75489

7

Hier ist eine einfacher generische Art und Weise:

import sys 

if sys.version_info[0] == 2: # Not named on 2.6 
    access = 'wb' 
    kwargs = {} 
else: 
    access = 'wt' 
    kwargs = {'newline':''} 

with open('test.csv', access, **kwargs) as csv_file: 
    writer = csv.DictWriter(csv_file, ['header1', 'header2']) 
    writer.writeheader() 
    for item in items: 
     writer.writerow(item) 

Das Prinzip ist hier nicht zu versuchen, die Unterschiede zwischen Python zu kämpfen 2 und 3 aber bedingten Code haben. Sie können nur so weit gehen, Code ohne diese Art von Test zu schreiben, früher oder später müssen Sie die Python-Version testen.

+0

Ich dachte, es könnte eine gute Lösung sein, '' kwargs' 'involviert zu bekommen. Es ist immer noch nicht schön, aber ist deutlich besser als all die Vervielfältigung, die ich hatte. Dies wird in meinem Szenario absolut funktionieren. Vielen Dank. – Tamerz

+0

Ich ging mit der Antwort, die @ skyline75489 gab, aber ich mag das immer noch für zukünftige Verwendung. Es gibt Zeiten, in denen ich genau das tun musste, aber nicht den besten Weg kannte. – Tamerz

+0

@Tamerz: Überprüfen Sie [meine Antwort] (http://stackoverflow.com/a/41913382/355230) auf eine ähnliche Frage. Es funktioniert in beiden Versionen von Python und behandelt das Öffnen von Dateien sowohl zum Lesen als auch zum Schreiben (plus. Wie 'open()', defaultiert den Lesemodus, wenn einer nicht explizit angegeben wurde). Es erfordert auch nicht die Verwendung globaler Variablen. – martineau