Unicode und argv

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
tb71
User
Beiträge: 3
Registriert: Freitag 29. Juni 2007, 13:29

Hallo,

fange gerade neu mit Python an und stehe schon vor einem (für mich unlösbaren) Problem: Wie kann ich Parameter mit nicht 8-bit-Zeichen übergeben/auswerten, z.B.:

ασγξκ3ς

Der Aufruf des Scripts erfolgt von der Kommandozeile, der Output (einfach nur Traces) geht in eine Datei um Probleme mit dem Encoding der Konsole auszuschließen:

Code: Alles auswählen

# pyargs: print information about the script arguments
import sys
import codecs
OUT = codecs.open("output.txt",encoding="utf-16",mode="w")
s1 = u"pyargs: %d arguments passed\r\n" % len(sys.argv);
OUT.write(s1)
for i in sys.argv:
  s2 = i.decode(argv_encoding)
  s2 = u"pyargs: argument " + s2 + "\r\n"
  OUT.write(s2)
OUT.close()
Ach ja, Python 2.5.1 unter Windows (XP).

Leider habe ich bislang trotz intensiver Suche noch keine Lösung gefunden. Auch ein Start des Interpreters mit Parameter "-U" hat keine Auswirkung.

Liebe Grüße und schon mal Danke im Voraus!

Thomas
BlackJack

Der Quelltext dürfte einen NameError provozieren, weil `argv_encoding` nirgends gebunden wird.

Wie die Daten in `sys.argv` kodiert sind, hängt vom aufrufenden Programm ab. Da musst Du entweder raten und hoffen, dass Deine Annahmen stimmen, oder dem Benutzer die Möglichkeit geben eine Kodierung explizit als Option dem Programm mit auf den Weg zu geben.

Die Frage ist am Anfang übrigens etwas unpräzise: Ob Zeichen mit 8 Bit darstellbar sind, oder nicht, hängt auch von der Kodierung ab. Das Beispiel lässt sich als iso-8859-7 kodiert nämlich durchaus mit 8 Bit pro Zeichen darstellen.
lunar

tb71 hat geschrieben:

Code: Alles auswählen

# pyargs: print information about the script arguments
import sys
import codecs
OUT = codecs.open("output.txt",encoding="utf-16",mode="w")
s1 = u"pyargs: %d arguments passed\r\n" % len(sys.argv);
OUT.write(s1)
for i in sys.argv:
  s2 = i.decode(argv_encoding)
  s2 = u"pyargs: argument " + s2 + "\r\n"
  OUT.write(s2)
OUT.close()
Dieser Code ist so nicht lauffähig, da argv_encoding überhaupt nicht definiert ist. Vielleicht solltest du mal sys.getfilesystemencoding ausprobieren. Auch das Wiki schadet nie: [wiki]Von Umlauten, Unicode und Encodings[/wiki]
Benutzeravatar
Masaru
User
Beiträge: 425
Registriert: Mittwoch 4. August 2004, 22:17

Leider ist sys.getfilesystemencoding() keine 100%ige Absicherung dafür, dass auch das, was hinneinkommt, wirklich in dem Codec codiert ist.

Zudem kann auf einigen Betriebssystemen die Methode "None" zurückliefern (z.B. HP-UX) was denn die .decode() Methode crashen lässt (erwartet schließlich ein String).

>>Masaru<<
lunar

Masaru hat geschrieben:Zudem kann auf einigen Betriebssystemen die Methode "None" zurückliefern (z.B. HP-UX) was denn die .decode() Methode crashen lässt (erwartet schließlich ein String).
Tja, selbst schuld, wer so exotisches Zeuch einsetzt ;)

Vielleicht kann man sich ja auch von Gerolds encodinghelper.py Anregungen zum Bestimmen des Encodings holen.
tb71
User
Beiträge: 3
Registriert: Freitag 29. Juni 2007, 13:29

Hallo,
Masaru hat geschrieben:Leider ist sys.getfilesystemencoding() keine 100%ige Absicherung dafür, dass auch das, was hinneinkommt, wirklich in dem Codec codiert ist.

Zudem kann auf einigen Betriebssystemen die Methode "None" zurückliefern (z.B. HP-UX) was denn die .decode() Methode crashen lässt (erwartet schließlich ein String).
Was fehlte, war im Code ein

Code: Alles auswählen

argv_encoding = sys.getfilesystemencoding()
Das beschriebene Verhalten ist leider trotzdem wie angemerkt.

So exotisch ist mein Wunsch ja (denke ich) eigentlich nicht, dass Parameter unter Windows auch korrekt vom Script verarbeitet werden können.

Aufgerufen wird das ganze aus cmd.exe (unter Windows XP), ein C-Programm kriegt die Parameter ganz korrekt als Unicode mit wenn vom Betriebssystem mittels Unicode-API erfragt.

Nur leider scheints bei jedem zu funktionieren (ich finde dazu leider in der Dokumentation bzw. per google nichts relevantes) nur bei mir nicht und ich frage mich warum

lg.
Thomas[/code]
tb71
User
Beiträge: 3
Registriert: Freitag 29. Juni 2007, 13:29

Hallo,

nur für den Fall, dass es jemanden interessiert hier meine Lösung:

Command Line auslesen mittels

Code: Alles auswählen

ctypes.windll.kernel32.GetCommandLineW()
Die API

Code: Alles auswählen

[win32api|win32ui].GetCommandLine()
geht nicht (kein Unicode...)

Mittels

Code: Alles auswählen

ctypes.windll.shell32.CommandLineToArgvW()
splitten.

Wenns "schöner" geht, bin ich für jeden Input dankbar.

lg.
Thomas
Antworten