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
fiveyears
User
Beiträge: 7
Registriert: Donnerstag 31. Januar 2013, 16:44

Hallo,

ich habe einen Unicode-String "Béla", der wird encodiert zu "Be\u0301la". Diesen String speichere ich in einemPref-File und lade ihn später wieder ein in eine Variable B.

doch mache ich :

Code: Alles auswählen

print (B)
kommt jetzt nicht Béla raus, sondern Be\u0301la !
Schreibe ich

Code: Alles auswählen

print(u'Be\u0301la')
, dann erscheint wieder Béla. Leider kann ich ja nicht

Code: Alles auswählen

print (u'B')
schreiben, weil dann einfach B erscheint. Ich komme hier nicht weiter, auch weil es in Python3 kein B.decode("utf-8") mehr gibt.

Mein System ist OSX, alles ist auf utf-8 eingestellt, ich nutze Eclipse mit PyDev und komme nicht weiter.

Danke und Gruß fiveyears
BlackJack

@fiveyears: Wo, wie, und warum kodierst Du die Zeichenkette denn als 'Be\u0301la'? Lass das doch einfach sein. :-)
fiveyears
User
Beiträge: 7
Registriert: Donnerstag 31. Januar 2013, 16:44

Danke für die Antwort:

Ich kodiere selbst gar nicht:

Code: Alles auswählen

this_bundle_id= "irgendwas"
lastAlbum=u'Béla'
os.system("defaults write " + this_bundle_id + " last_album \"" + lastAlbum + "\" ")
Im Pref-File lese ich Béla

Code: Alles auswählen

            preference_value = subprocess.check_output("defaults read " + this_bundle_id + " " + last_album + "  2>&1; exit 0", shell=True)
            preference_value=preference_value.decode("utf-8")
            preference_value = preference_value.replace("\n", "")
            print (preference_value)
und schwupp, das Ergebnis ist Be\u0301la
fiveyears
User
Beiträge: 7
Registriert: Donnerstag 31. Januar 2013, 16:44

fiveyears hat geschrieben:

Code: Alles auswählen

            preference_value=preference_value.decode("utf-8")
Ich habe durch Zufall den Fehler gefunden, die Zeile muss heißen:

Code: Alles auswählen

            preference_value=preference_value.decode("unicode_escape")
BlackJack

@fiveyears: Das sieht beides recht gruselig aus. `os.system()` sollte man meiden, da das diverse Probleme hat, die auch schon die C-Funktion hat, von der schon lange bevor es Python gab deshalb auch in C schon abgeraten wurde.

Das Zusammensetzen von Zeichenketten mit ``+`` ist eher BASIC als Python. Dafür gibt es Zeichenkettenformatierung mit der `format()`-Methode auf Zeichenketten oder dem ``%``-Operator.

Wenn man "-Zeichen in einer literalen Zeichenkette schreiben möchte, dann nimmt das Zeichen sinnvoller Weise nicht als Begrenzer für die Zeichenkette. Dann braucht man es auch nicht escapen.

Letztlich ist das manuelle Zusammensetzen von Zeichenketten für externe Kommandos aber sowieso Mist weil fehleranfällig und unnötig. Damit wären wir beim `subprocess.check_output()`. Da wird eine unnötige Shell gestartet, die Argumente werden fehleranfällig an diese übergeben, und dann wird eine Methode verwendet die den Rückgabecode des Programms testet und das Shellkommando enthält explizit Code der das unterläuft. Wie kommt man denn auf so eine Idee? Die Umleitung der Fehlerausgabe auf Shell-Ebene ist auch etwas was man mit `subprocess` selbst machen kann.
fiveyears
User
Beiträge: 7
Registriert: Donnerstag 31. Januar 2013, 16:44

Hallo,

ich bin kein Pythoniker, eher bash, perl, Objective-C.

Das os.system() habe ich ebenso wie subprocess aus Beispielen übernommen. Ich dachte auch, es gibt einfachere Varianten wie z. B. in der Shell oder perl

Code: Alles auswählen

ergebnis=$(terminal-befehl ...)
aber anscheinend nicht. Das os.system() funktioniert, ebenso wie subprocess - was sollte man hier besser nehmen?


Gruß fiveyears
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ungetestet:

Code: Alles auswählen

import subprocess

def get_output(args):
    return subprocess.check_output(args).rstrip('\n')

result = get_output(['defaults', 'read', this_bundle_id, last_album])
print(result)
BlackJack

@fiveyears: Es „funktioniert” ist im Zusammenhang mit `os.system()` wohl ein dehnbarer Begriff. Es wird eine Shell gestartet und der wird eine selbst zusammengebaute Zeichenkette übergeben. Die Werte die Du da einsetzt, dürfen nichts enthalten was die Shell irgendwie besonders behandelt. `lastAlbum` kann problematisch werden wenn dort beispielsweise Dollarzeichen drin vorkommen. Oder doppelte Anführungszeichen. Oder Ausrufezeichen!

Beim Rückgabewert von `os.system()` gibt es keine Möglichkeit fest zu stellen ob der von dem über die Shell gestarteten Programm ist, oder von der Shell selber.

Was man also besser nicht nehmen sollte sind Lösungen, die eine Shell zwischen dem eigenen Programm und dem Externen starten, weil man sich dann Gedanken um diesen eigentlich unnötigen Zwischenschritt machen muss, was der mit den Daten anstellt.

Bei spezieller Syntax um ganz bestimmte Sachen einfacher zu machen sind die Python-Entwickler sehr zurückhaltend. Es soll halt eine allgemeine Programmiersprache ohne Spezialisierung auf ein Anwendungsfeld in der Sprache selbst sein und mit möglichst einfacher, übersichtlicher Syntax. Bash und Perl dagegen sind mit einem Schwerpunkt entworfen worden, Shell-Skripting und Textverarbeitung.

Die sauberste Lösung wäre hier wahrscheinlich über `PyObjC` die entsprechende
API zu den Einstellungen zu verwenden statt über externe Programme zu gehen, die ihrerseits genau diese API verwenden werden.
fiveyears
User
Beiträge: 7
Registriert: Donnerstag 31. Januar 2013, 16:44

Hallo,

ich habe jetzt auf subprocess.check_output() und subprocess.call() umgestellt, Ergebnis ist das gleiche, bin einsichtig

Grüße
fiveyears
User
Beiträge: 7
Registriert: Donnerstag 31. Januar 2013, 16:44

Die aktuelle Python-Version in OSX Mountain Lion 10.8 ist 2.7. In dieser Version gibt es, obwohl wir schon im Jahre 2013 leben, immer noch Unterschiede zwischen ascii-Strings und Unicode-Strings. Ich entwickle in Eclipse mit PyDev und Python 3.3, lasse das Ergebnis dann aber mit Python 2.7 unter OSX laufen und laufend meckert Python wegen ascii-Codierungsfehlern. Manchmal denke ich, dass es immer noch amerikanische Entwickler gibt, die gar nicht wissen, dass es andere Sprachen außer "Ascii-English" gibt.

Aber auch in Python 3.3 sieht es noch nicht so gut aus. Zum Beispiel das ganz normale č wie in česky macht mir große Probleme. Man kann es unicode-mäßig als u'c\u030c', d. h. "c kombiniert mit dem Haček", aber auch als u'\u010d', d. h. "c mit Haček" kodieren. Manche Browser, Programme oder Betriebssysteme machen es so, manche so, manchmal hängt es auch einfach an der Art der Tastatureingabe ab. Bloß wenn ich in Python

Code: Alles auswählen

if česky==česky:
vergleiche. kann mir passieren, dass dann False raus kommt. Wie kann man dieses Verhalten denn umgehen. Ich wünsche mir:

Code: Alles auswählen

if č==c: # False
if č==č: # True
Übrigens gilt dies auch für é und andere Kombinationen wie ñ, da gibt es immer ein Unicode-Zeichen und eine kombinierte Form


Gruß fiveyears
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Ja, es gibt halt viele Normalisierungsarten. Schau dir mal unicodedata.normalize an.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
fiveyears
User
Beiträge: 7
Registriert: Donnerstag 31. Januar 2013, 16:44

Danke, das habe ich überlesen, obwohl es genau das war, was ich brauchte! :D
Antworten