list in txt problem mit unicode

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
python71
User
Beiträge: 5
Registriert: Freitag 25. März 2011, 11:15

version python 2.7.1
ich lese mit modul xlrd eine excel und zwar jede Zeile in eine list.

das klappt und eine list sieht zB so aus.

[1.0, u'name', u'ist \u20ac', 100.0, u'und', u'\xfcber', u'200 \u20ac', u'%', '']

iteriere ich über die list und lasse mir jedes in IDLE mit print anzeigen sieht es auch noch gut aus.

1.0
name
ist €
100.0
und
über
200 €
%

so mein ziel war es nun diese Ausgabe

1.0
name
ist €
100.0
und
über
200 €
%
in eine test.txt zu schreiben.

mit dem befehl f = open(meinfile,'w') klappt es nicht, da System bringt meldung.

cant codec ascii usw........

ich frage mich wie die typen float und unicode zum beispiel die in der list enthalten sind ich so in eine txt datei schreiben kann wie ich die daten mit dem Auge sehen wenn ich die einzelnen listindexe mit print ausgebe im idle.

ich kapier das nicht.

ich hoffe mir kann einer helfen.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Wenn ich deinen kryptischen Text richtig verstanden habe, willst du:

Code: Alles auswählen

f.write('\n'.join(unicode(line) for line in deine_liste))
BlackJack

@python71: In der Liste sind Unicode-Objekte enthalten. Wenn Du Die in IDLE per ``print`` ausgibst ist das kein Problem, denn Python kann herausfinden welche Kodierung IDLE erwartet. Dateien haben aber keine Kodierung, also musst Du da explizit dafür sorgen, dass die Unicode-Zeichenketten in "Byte"-Ketten, also `str` umgewandelt werden.

@snafu: Wohl eher nicht. Es sind keine Zeilen in der Liste, der Name `line` passt also nicht. Und genau der Umstand dass das `unicode` ist, führt doch zum Fehler.
python71
User
Beiträge: 5
Registriert: Freitag 25. März 2011, 11:15

@Blackjack

genau das is ja mein problem:

in idle z.B unicode 'test' kann ich in beide Richtungen umwandeln

>>> a =u'test'
>>> a.encode()
'test'
>>> _.decode()
u'test'
diesen unicode der in meiner List ist aber nicht dann komm fehlermeldung siehe unten.
>>> t = u'ist \u20ac'
>>> t.encode()

Traceback (most recent call last):
File "<pyshell#49>", line 1, in <module>
t.encode()
UnicodeEncodeError: 'ascii' codec can't encode character u'\u20ac' in position 4: ordinal not in range(128)

In der Zwischenzeit habe ich mal in der python doku gestöbert. Dort fand ich das modul codecs.

Mein code sieht nun so aus und er tut. Warum wieso kann ich nicht sagen aber er tut.
Zu Info ich bin absoluter Anfänger.

Code: Alles auswählen

#-*- coding: utf-8 -*-
#Open the workbook
# mit Python excel file lesen xlrd geht nur bis Python 2.7 und Excel muss ein xls file sein

import xlrd
import codecs

datei = xlrd.open_workbook('C:\\Test\\frank.xls')
tabelle = datei.sheet_by_index(0)
f = codecs.open('test.txt', encoding='utf-8', mode='w',buffering = 1)

for zeile in range(tabelle.nrows):
    l = tabelle.row_values(zeile)
    for i in range(0,tabelle.ncols):
        print (l[i])
        if type(l[i]) is unicode:
            f.write (l[i])
        else:
            dummy = str(l[i])
            f.write(dummy)
    f.write('\n')
        

f.close()
Danke jedenfalls
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Du musst in dem Fall beim Enkodieren auch die Kodierung mit angeben:

Code: Alles auswählen

>>> t.encode('utf-8')
'ist \xe2\x82\xac'
Ich habe in dem Zusammenhang etwas gebastelt, das ich für ein eigenes Projekt benötige: _stringutils.py. Es konvertiert übergreifend für Python 2 und Python 3 wahlweise in die native String-Form oder in die "alternative" Form (Unicode unter Python 2, Bytes unter Python 3). Dabei kommt es auch mit Objekten klar, die keine Strings sind (wie z.B. deine Zahlen). Eventuell hilft dir das. Ansonsten gibt es im schon von dir genannten Codecs-Modul aber auch noch ein paar Klassen, die hilfreich sein könnten. Habe mich ehrlich gesagt noch nicht so genau mit dem Modul beschäftigt.
BlackJack

@python71: Wenn Du einfach nur `encode()` oder `decode()` ohne Argument verwendest, dann wird 'ASCII' angenommen. Das fällt halt auf die Nase wenn irgend etwas ausserhalb des ASCII-Wertebereichs vorkommt. Du musst da schon eine konkrete Kodierung angeben. Für das Kodieren Eine, die alle Zeichen kodieren kann, und für das Dekodieren Diejenige, in der die Zeichen auch mal kodiert wurden.

Das `buffering`-Argument bei `codecs.open()` brauchst Du nicht angeben. Es sei denn Du willst etwas anderes als die Voreinstellung.

Anstelle von `range()` solltest Du `xrange()` verwenden und bei der inneren Schleife ist das wohl auch überflüssig, oder ist die Liste länger als ``tabelle.ncols``? Selbst dann würde ich wohl eher die Elemente aus der Liste ausschneiden (slicing) und direkt über die Elemente iterieren statt diesen unnötigen Index `i` mit zu schleppen.

Beim Typtest ist ein Problem: ``is`` vergleicht nicht auf Gleichheit, sondern auf Objektidentität. Und man testet da auch eher mit `isinstance()` statt mit `type()`.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

BlackJack hat geschrieben:@snafu: Wohl eher nicht. Es sind keine Zeilen in der Liste, der Name `line` passt also nicht.
Um darauf noch einzugehen: Wenn der OP über die Elemente seiner Liste iteriert, um das jeweils aktuelle Objekt mittels `print` auszugeben, dann sind das durchaus Zeilen für mich. So wie ich es verstanden habe, möchte er die Art der Konsolenausgabe genau so in der entsprechenden Datei haben.

Oder ging dein Einwand in die Richtung, dass ich bei der Benennung in der for-Schleife nicht ein Wort gewählt habe (etwa `elem`), welches die Objekte im Kontext der Liste beschreibt, sondern sie stattdessen nach ihrem Verwendungszweck (Zeile) benannt habe?
BlackJack

@snafu: So habe ich das gar nicht gesehen. Ich fand es verwirrend weil die Liste insgesamt ja eine Zeile mit Spaltenwerten darstellt -- jedenfalls in der Excel-Tabelle wo sie entnommen wurde. Also wäre eine passende Bezeichnung dafür vielleicht `row` und ein ``(line for line in row)`` bringt mich mental halt ein wenig ins schleudern. :-)
Antworten