2015-04-24 12 views
11

EDYCJA: Umieściłem go w tytule, ale po prostu zdałem sobie sprawę, że nie wspomniałem o tym w ciele. Wydaje się to być specyficzne dla systemu Windows.Pisanie pliku .CSV w języku Python, który działa zarówno w języku Python 2.7+, jak iw języku Python 3.3+ w systemie Windows

Mam trudności z zapisaniem danych wyjściowych przy użyciu modułu Python csv w skrypcie, który działa zarówno w języku Python 2.7, jak i 3.3.

pierwszej próbie, która działa zgodnie z oczekiwaniami w Pythonie 2.7:

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

Jednak, gdy to samo jest prowadzony w Pythonie 3.3 skończyć z:

TypeError: 'str' does not support the buffer interface 

Więc zmienić 'wb' do 'wt' i działa, ale teraz mam dodatkowy pusty wiersz co drugą linię w pliku.

Aby to naprawić, zmienić:

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

do:

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

Ale teraz, to łamie Python 2.7:

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

wiem, może po prostu zrobić coś takiego :

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) 

Jednak ma to kilka poważnie szkodliwych powielaczy.

Czy ktoś ma czystszy sposób robienia tego?

EDIT: Dane Test jest prosty i nie ma żadnych nowych linii lub cokolwiek:

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

Nie możesz po prostu użyć '' w'' zamiast '' wb'' lub ''wt''? – nathancahill

+0

Czy ciągi znaków w łańcuchach 'items' listują' unicode', gdy uruchamiasz skrypt w Pythonie 2? Czy wartości są zawsze ASCII, czy mogą zawierać dodatkowe znaki, które muszą być zakodowane? Nawet jeśli możesz uruchomić ten sam kod w obu wersjach Pythona, możesz nie uzyskać takich samych wyników! – Blckknght

+0

@Blckknght - Dodałem dane testowe do dolnej części pytania. To tylko tekst ASCII. – Tamerz

Odpowiedz

6

Próbowałem kilka sposobów. O ile widzę, proste używając 'w' może być rozwiązanie:

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

Jeśli to zrobię, nadal otrzymuję puste linie co drugi wiersz. Czy próbowałeś tego w Windows lub na czymś innym? – Tamerz

+0

@Tamerz Otrzymujesz dodatkowe nowe linie, ponieważ masz dodatkowe nowe linie w swoich danych ... '.strip()' może być tym, czego potrzebujesz. – gboffi

+0

@Tamerz Próbowałem z fałszywymi danymi i wszystko poszło dobrze. Więc myślę, że coś jest nie tak z twoimi danymi. – skyline75489

7

Oto prostszy sposób ogólna:

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) 

Zasada tutaj nie próbować walczyć z różnic między Python 2 i 3, ale aby mieć kod warunkowy. Możesz pisać tylko tyle, by pisać bez tego testu, prędzej czy później będziesz musiał przetestować wersję Pythona.

+0

Pomyślałem, że może być zaangażowany '** kwargs' może być dobrym rozwiązaniem. Nadal nie jest ładna, ale jest znacznie lepsza niż wszystkie moje duplikacje. To będzie absolutnie działać w moim scenariuszu. Dziękuję Ci. – Tamerz

+0

Poszedłem z odpowiedzią, że @ skyline75489 dał, ale nadal lubię to do wykorzystania w przyszłości. Są chwile, w których muszę to zrobić, ale nie znałem najlepszego sposobu. – Tamerz

+0

@Tamerz: Sprawdź [moja odpowiedź] (http://stackoverflow.com/a/41913382/355230) na podobne pytanie. Działa w obu wersjach Pythona i obsługuje otwieranie plików zarówno do odczytu, jak i zapisu (plus np. 'Open()', domyślnie do trybu odczytu, jeśli nie został określony jawnie). Nie wymaga również użycia zmiennych globalnych. – martineau