Problem mit Unicode und Liste

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
Schreiberling
User
Beiträge: 5
Registriert: Montag 20. Februar 2006, 19:14

Hi!

Ich habe bereits die Such-Funktion benutzt und etwas über Unicode gefunden, allerdings hat das mein Problem noch nicht gelöst. Ich habe ein Python-Programm geschrieben, das standardmäßig Unicode verwendet:
# -*- coding: UTF-8 -*-
Dateien lesen und schreiben klappt alles mit Unicode. Nur:
Wenn ich eine Liste fülle, wird sie in ASCII konvertiert (oder so angezeigt beim print-Befehl).
Schlussendlich brauche ich die Möglichkeit, den Inhalt eines Dictionarys (das auf die Liste zurückgeht) in der Konsole vernünftig (in Unicode) anzeigen zu lassen.
Kann man eine Liste oder ein Dictionary nach Unicode konvertieren, oder wenn das nicht geht, wenigstens mit Unicode ausdrucken?

Danke.
BlackJack

Wenn man ein Objekt mit ``print`` ausgibt, dann bestimmt das Objekt selbst über seine `__str__()` Methode, wie es als Zeichenkette aussieht. Bei Listen und Dictionaries wird der Inhalt mit `repr()` formatiert.

Du musst also den Inhalt selbst ausgeben/formatieren und nicht das Containerobjekt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Schreiberling hat geschrieben:Ich habe ein Python-Programm geschrieben, das standardmäßig Unicode verwendet: # -*- coding: UTF-8 -*-
Hi Schreiberling!

UTF-8 != Unicode
Skript-Encoding <--> Python Unicode <--> Externes Encoding
siehe http://www.python-forum.de/viewtopic.php?t=5095

Du kannst die Ausgabe von

Code: Alles auswählen

str(objekt)
oder von

Code: Alles auswählen

repr(objekt)
zuerst in eine Variable schreiben, den Inhalt der Variable in das gewünschte Encoding umwandeln und dann erst ausgeben.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Schreiberling
User
Beiträge: 5
Registriert: Montag 20. Februar 2006, 19:14

Wie schreibt man das genau? Ich bin Anfänger!

Genaugenommen habe ich ein Dictionary, das als Key ein Wort hat und als Value eine Zahl. Nun lasse ich mir die 30 Keys mit den höchsten Werten ausdrucken. Der Befehl am Schluss lautet:

print frequencies[:30].

Ich hab's dann schonmal mit print unicode(frequencies[:30]) versucht, was natürlich nicht klappte, oder mit

for word in frequencies[:30]:
... word = word.decode("utf-8")
... print word

Den Code für das Dictionary habe ich übernommen, daher weiß ich nicht ganz genau, was man da machen kann.
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Damit Du irgendwas "vernünftig" in Unicode auf der Konsole anzeigen kannst muss die Konsole Unicode verstehen, das hat rein gar nichts mit Python zu tun. Ganz davon abgesehen: Unicode ist kein Zeichen-Encoding. Im Normalfall wird die Konsole utf-8 verstehen, was eine Kodierung ist die möglichst viele Unicode-Codepoints darstellen kann, und wenn Du einen String ausgibst musst Du diesen dann nach utf-8 kodieren.

Aber, da ich nicht davon ausgehen dass Du eine Unicode-Enabled Konsole hast (was selbst unter Linux immer noch nicht standard ist), willst Du im Normalfall wahrscheinlich sowas wie:

Code: Alles auswählen

for elem in frequencies[:30]:
    print elem.decode("utf-8").encode("iso-8859-15")
Wobei unter Windows anstelle von iso... cp1252 zu schreiben ist. Die Standardeinstellung für eine Konsole ist nun mal noch ein Latin-Zeichensatz. Das decode("utf-8") bedeutet so viel wie dass Du davon ausgehst dass elem ein String im UTF-8 Format ist. Ich hab das nur aus einem Deiner Programme übernommen; wenn Du einen UnicodeDecodeError bekommst probier das mal wegzulassen und nur letzteres (dann hast Du nämlich schon unicode-strings in dem Array).

Sonst, wenn ich das falsch verstehe: poste mal Deine Ausgabe, ich hab nicht das Gefühl dass Du wirklich verstehst was hinter Unicode steckt und deswegen eher im Dunkeln stocherst als irgendwas anderes. Nur wenn Du das Problem nicht präzisierst kann ich Dir auch nicht helfen.
--- Heiko.
Schreiberling
User
Beiträge: 5
Registriert: Montag 20. Februar 2006, 19:14

@modelnine: Dein herablassendes Gerede kannst du dir sparen. Ich glaube eher, dass du nicht verstehst, dass das ein Python-Problem ist. Meine Konsole ist auf Unicode eingestellt, was ich auch schon überprüft habe. Dateiinhalte, die ich mit Python ausgedruckt habe, werden richtig angezeigt, nur eben nicht Inhalte von Listen oder Dictionaries:

http://www.python-forum.de/viewtopic.ph ... ht=unicode
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Sorry, es war nicht herablassend gemeint und wenn Du es so aufgefasst hast tut mir das leid, aber man wird doch wohl noch ansprechen dürfen dass meiner Meinung nach Du das Problem ungenügend beschrieben hast und das darauf hinweist dass Du eher mal schauen solltest ob Du das was hinter Unicode (in Python) steckt verstanden hast!

Auf jeden Fall: Wenn das Dein Problem ist hat Dir Gerold schon die richtige Antwort dafür gegeben, und zwar den Unterschied zwischen repr() und str() auf ein Objekt. Bei Container-Typen wird der gesamte Inhalt mittels repr() formatiert, sprich:

Du musst selbst eine Methode schreiben um den Inhalt auszugeben, und eben str() benutzen auf den Inhalt der Objekte. Dann kriegst Du die richtige Ausgabe.

Also, wenn Du eine Liste von Unicode-String-Objekten hast:

Code: Alles auswählen

for blah in frequencies[:30]:
    print blah.encode("utf-8")
(damit das Unicode-Objekt als UTF-8 ausgegeben wird, was die Konsole dann interpretiert).

Da die Antwort schon vorhanden war (gerold hatte sie schon in sehr ähnlicher Form geschrieben) aber das anscheinend Dein Problem nicht behoben hat war meine Meinung schlicht und ergreifend dass Du Dir nicht im klaren bist dass Unicode auf der Konsole eine Konsole braucht die UTF-8 unterstützt (da im Normalfall UTF-8 bei Unicode-Konsolen gebraucht wird), oder halt ganz allgemein den Unterschied zwischen Byte-String und Unicode-Strings in Python nicht verstanden hast.

Deine letzte Antwort liefert auch wieder nicht genügend Informationen um Dir helfen zu können, denn was der Inhalt von frequencies[:30] ist kann ich auch wieder nur raten, sprich, ob der obige Code Dir hilft.

Bitte, bitte, poste doch mal mehr von dem was Du machen willst, was die Ausgabe ist, warum die falsch ist, usw., dann hilft Dir auch jemand wirklich! Solange ist es echt nur im Dunkeln stochern für uns (und glaub mir, ich will Dir helfen, nur so versteh ich Dein Problem nicht und meine Kristallkugel ist OOO).
--- Heiko.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hi Schreiberling!
Schreiberling hat geschrieben:Ich glaube eher, dass du nicht verstehst, dass das ein Python-Problem ist.
Tut mir leid, aber ich glaube eher, dass du nicht verstanden hast wie das so mit Unicode und den Encodings läuft.
Schreiberling hat geschrieben:Meine Konsole ist auf Unicode eingestellt, was ich auch schon überprüft habe.
Deine Konsole ist ziemlich sicher nicht auf Unicode eingestellt. Wie hast du das geprüft? Welches Betriebssystem verwendest du?
Schreiberling hat geschrieben: Dateiinhalte, die ich mit Python ausgedruckt habe, werden richtig angezeigt, nur eben nicht Inhalte von Listen oder Dictionaries
Da spielt der Zufall auch eine Rolle. Ich hatte dir einen Link gepostet, der dieses Thema anfängerfreundlich erklären sollte. (Wink mit dem Betonpfeiler...) -->> http://www.python-forum.de/viewtopic.php?t=5095

Da ich keinen Beispielcode von dir gesehen habe, kann ich nur raten:
Du willst einfach nur den Inhalt einer Liste, die Dictionaries enthält, in die Konsole schreiben. Als Format genügt dir die Ausgabe von repr().
Wenn du deine Liste ohne Umlaute mit *print* ausgibst, dann funktioniert die Ausgabe. Enthält eines der Dictionaries ein Umlaut, dann gibt es einen Fehler. (Beim nächsten Mal bitte ausführliches Traceback.)

Code: Alles auswählen

import sys
stdout_encoding = sys.stdout.encoding or sys.getfilesystemencoding()
print repr(frequencies[:30]).decode("utf-8").encode(stdout_encoding)
Mal sehen ob dich das weiter bringt.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Schreiberling
User
Beiträge: 5
Registriert: Montag 20. Februar 2006, 19:14

modelnine hat geschrieben:

Code: Alles auswählen

for blah in frequencies[:30]:
    print blah.encode("utf-8")
Den Code habe ich vor ein paar Tagen schon einmal ausprobiert, die Python-Konsole meinte in etwa: "list object has no attribute encode".

Ich arbeite mit Linux, die Konsole ist auf Unicode eingestellt (steht im Menü). Dass ich Unicode eingestellt habe, merke ich daran, dass Text, den ich von einer Unicode-Datei einlese und mit Python ausdrucke, richtig angezeigt wird. Schalte ich die Konsole auf ISO-8859-1, so wird er nicht mehr richtig angezeigt. Das Problem bestand übrigens auch unter PythonWin, als ich das Python-Script in ISO-8859-1 abgespeichert und den entsprechenden coding-Eintrag gesetzt hatte. Die Konsole zeigt dort mit ISO-8859-1 an.
Wenn ich einen Unicode-Text einlese und in eine Liste packe, wird er zu ASCII (bemerkbar bei "print list"), wenn ich die Liste wieder in eine Datei schreibe, wird er wieder Unicode. Also ist es doch ein Python-Problem, ich meine natürlich, wie Python mit den Kodierungen umgeht, denn print "äöü" verfälscht nichts, list.append("äöü") und print list hingegen schon.

Dass repr() funktioniert, kann schon sein, aber das "in eine Variable schreiben" hatte ich nicht verstanden.

Das Tutorial für Unicode habe ich mir selbstverständlich angesehen, sogar bevor ich den Thread geöffnet habe. Es ist zwar toll, aber man sieht den Wald vor lauter Bäumen nicht und das Problem von Unicode-Tutorials im Allgemeinen ist, dass sie immer nur von popeligen Strings ausgehen, die man in die Konsole tippt, dabei musste ich sehen, wie ich den Code mit einem Dictionary verbinde und in eine Funktion schreibe, deren Code gar nicht von mir stammt. Außerdem ist im Tutorial nichts über Listen, Dictionaries und auch nicht über repr() drin. Ich werd's mal ausprobieren.

Aber trotzdem Danke für eure Mühe.
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Also ist es doch ein Python-Problem, ich meine natürlich, wie Python mit den Kodierungen umgeht, denn print "äöü" verfälscht nichts, list.append("äöü") und print list hingegen schon.

Dass repr() funktioniert, kann schon sein, aber das "in eine Variable schreiben" hatte ich nicht verstanden.
Ohne dass Du mir wieder Überheblichkeit nachsagst: das ist kein Python-Problem, das ist ein Verständnisproblem Deinerseits im Unterschied zwischen repr() und str().

Ich mach einfach mal ein Beispiel, vielleicht hilft Dir das, sonst, wenn Du weiterhin uns raten lässt was Du eigentlich machen willst können wir Dir definitiv nicht helfen. In Deinem letzten Post taucht wieder garnichts auf was irgendwo darauf hindeuten könnte was Du genau machen willst und was in frequencies eigentlich drinsteht.

So, jetzt aber das Beispiel:

Code: Alles auswählen

modelnine@phoenix ~ $ python
Python 2.4.2 (#1, Feb  5 2006, 17:30:13)
[GCC 4.0.2 (Gentoo 4.0.2-r3, pie-8.7.8)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> x = u"äöü"
>>> x # repr() Ausgabe von u, das ist die Standardeinstellung für den Wert eines
      # Ausdrucks auf der Kommandozeile.
u'\xe4\xf6\xfc'
>>> print x.encode("utf-8") # Ausgabe des Unicode-Strings in utf-8
ÀöÌ # Auf meiner Konsole nicht zu erkennen, weil auf iso-8859-15 eingestellt.
>>> print x.encode("iso-8859-15") # Ausgabe des Unicode-Strings in latin-15
äöü # Aaahhh... Schon besser.
>>> y = [x] # Mache eine Liste draus mit einem element.
>>> print y # Bei der Ausgabe wird str() auf das Objekt aufgerufen. Containertypen
      # formatieren den Inhalt aber mittels repr(), siehe wie das oben aussieht für einen
      # Unicode string.
[u'\xe4\xf6\xfc']
>>> print y[0].encode("utf-8") # Ausgabe des ersten Elements in utf-8.
ÀöÌ
>>> print y[0].encode("iso-8859-15") # Ausgabe des ersten Elements in latin-15.
äöü
>>>
modelnine@phoenix ~ $
Alles klar?
--- Heiko.
Schreiberling
User
Beiträge: 5
Registriert: Montag 20. Februar 2006, 19:14

str() und repr() habe ich noch gar nicht ausprobiert und deshalb darüber auch noch gar nichts ausgesagt.

Das genaue Code-Beispiel ist folgendes:

count = {alle möglichen Einträge}

frequencies = [(num, word) for (word, num) in count.items()]
frequencies.sort()
frequencies.reverse()
print frequencies[:30]
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Soo....

Das sieht doch schon besser aus.

Dann mach mal:

Code: Alles auswählen

for num, word in frequencies[:30]:
  print "%s: %s" % (num,word.encode("utf-8"))
anstelle von dem Print über den Container (sprich die Liste, mit ihren enthaltenen Tupeln, die wiederum ein Container-Typ sind). Und freue Dich über die Ausgabe.

Voraussetzung dabei ist dass word ein unicode-string ist, und kein byte-string in utf-8-Kodierung. Wenn er letzteres ist, lässt Du das encode("utf-8") einfach weg.
--- Heiko.
Antworten