unicode/str an subprocess.Popen übergeben

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
pPilger
User
Beiträge: 45
Registriert: Montag 8. Februar 2010, 17:30

Hallo,
mal wieder die leidigen Umlaute.
Ich bekomme Daten aus einer Datenbank, die durch diese Abfrage in unicode in meinem Pythonscript landen.

Code: Alles auswählen

self.db_con = kinterbasdb.connect( dsn=self.db_name, user=self.db_user, password=self.db_pw,  charset='WIN1252' )
Daten daraus will ich an ein externes Programm übergeben. Der Lame-Encoder für mp3-Dateien soll die id3-Tags schreiben:

Code: Alles auswählen

p = subprocess.Popen([c_lame_encoder, "--add-id3v2",  c_id3_title, c_id3_title_value, c_id3_author,  c_id3_author_value,  c_source_file, c_dest_file ],  stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate(  )
Hier bekomme ich den ascii-decode Error, wenn in c_id3_title oder c_id3_author Umlaute drin sind.
Wenn ich den Typ dieser variablen prüfe erhalte ich
<type 'unicode'>
Nun habe ich per:

Code: Alles auswählen

c_id3_title_value = podcast_sendung[1].encode( "cp1252" )
in str umgewandelt, aber trotzdem erhalte ich bei der Zeile "subprocess.Popen" den ascii-decode error.
Wo liegt da mein Fehler?
Das ganze soll auf win-XP, später ubuntu-linux laufen.
Danke für die Hilfe
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Die Fehlermeldung passt nicht zur Beschreibung. Wenn da tatsächlich unicode drin stünde, kann ja kein decode-Error auftreten. Bist Du Dir sicher, dass Der Fehler so lautet? Zeig uns doch mal ein minimales lauffähiges Beispiel, bei dem man den Fehler beobachten kann. Am besten tausche mal lame gegen ein Standard-Kommando aus, welches jeder schnell mal ausprobieren kann.

Zudem würde ich mal unabhängig von der DB mit festen Strings testen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
pPilger
User
Beiträge: 45
Registriert: Montag 8. Februar 2010, 17:30

Hyperion hat geschrieben:Die Fehlermeldung passt nicht zur Beschreibung. Zudem würde ich mal unabhängig von der DB mit festen Strings testen.
Sorry für meine Ungenauigkeit.
Wenn ich folgendes übergebe:

Code: Alles auswählen

c_id3_author_value = u"Max".encode( "cp1252" ) + " " + u"Müller".encode( "cp1252" )
erhalte ich diese Fehlermeldung:
Traceback (most recent call last):
File "D:\SRB_Tools\podcast_beamer.py", line 523, in <module>
lets_rock()
File "D:\SRB_Tools\podcast_beamer.py", line 494, in lets_rock
podcast_temp = encode_file( podcast_sendung )
File "D:\SRB_Tools\podcast_beamer.py", line 340, in encode_file
p = subprocess.Popen([c_lame_encoder, "--add-id3v2", c_id3_title, c_id3_title_value, c_id3_author, c_id3_author_value, c_source_file, c_dest_file ], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate( )
File "C:\Python26\lib\subprocess.py", line 621, in __init__
errread, errwrite)
File "C:\Python26\lib\subprocess.py", line 789, in _execute_child
args = list2cmdline(args)
File "C:\Python26\lib\subprocess.py", line 557, in list2cmdline
return ''.join(result)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xfc in position 0: ordinal not in range(128)

bei diesem Befehl:

Code: Alles auswählen

p = subprocess.Popen([c_lame_encoder, "--add-id3v2",  c_id3_title, c_id3_title_value, c_id3_author,  c_id3_author_value,  c_source_file, c_dest_file ],  stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate(  )
Ein type der variable c_id3_author_value sagt mir hier:
<type 'str'>
Fülle ich die variable so:
c_id3_author_value = u"Max" + " " + u"Müller"
sagt mir type logischerweise:
<type 'unicode'>
und ich bekomme diese Fehlermeldung an der gleichen Stelle wie oben:
UnicodeEncodeError: 'ascii' codec can't encode character u'\xfc' in position 76: ordinal not in range(128)

Vieleicht seht Ihr hier schon was ich falsch mache...
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ich würde mal sagen, dass Du in Deinem Quellcode keine Angabe über das Encoding machst. Das dürfte bei Dir fehlen:

Code: Alles auswählen

# coding: utf-8
(oder so ähnlich eben)

Ich wette, dass einige der Strings im Popen args-Paratemer uneinheitlich sind, also einige Unicode, andere Bytestrings. Kann das sein? Damit würde nämlich beim Zusammenbau der Parameter (augenscheinlich durch die "".join() Methode) implizit ein encoding bzw. decoding aufgerufen. Ohne Angabe des Encodings nimmt der Interpreter in Python 2.x eben ASCII an, weswegen das Decodieren beim Ziel Unicode schief läuft. Das ist immer der Fall, wenn Du Unicode und Bytestrings mischt, also bei Fehlermeldung Nummer eins.

Nummer zwei kommt wohl dadurch zustande, dass die Parameter irgend wann einmal eben in Bytestrings gewandelt werden müssen - eben dann, wenn die Python-Welt verlassen wird. Und auch dabei wählt der Interpreter dann eben das Default-Encoding ASCII, wenn kein Script weites Encoding eingestellt ist.

Ich würde es für sinnvoll halten, alle Parameter vorher in Bytestrings zu encodieren. Das Encoding hängt dabei natürlich vom Programm ab, welches die Daten entgegen nimmt. (sys.defaultencoding() wäre evtl. eine gute Wahl).

Du setzt diesen Beispielstring übrigens ziemlich umständlich zusammen ;-)

Code: Alles auswählen

c_id3_author_value = u"Max" + " " + u"Müller"
# ist doch dassselbe wie:
c_id3_author_value = u"Max Müller"
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
pPilger
User
Beiträge: 45
Registriert: Montag 8. Februar 2010, 17:30

Hyperion hat geschrieben:Ich würde mal sagen, dass Du in Deinem Quellcode keine Angabe über das Encoding machst. Das dürfte bei Dir fehlen:
Die ersten beiden Zeilen meines scriptes:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
ist daran was falsch? Hat bisher keine Probleme gemacht.
Hyperion hat geschrieben: Ich wette, dass einige der Strings im Popen args-Paratemer uneinheitlich sind, also einige Unicode, andere Bytestrings. Kann das sein?
Werd ich prüfen. Es knallt nur, wenn Umlaute vorkommen, sonst gehts prima.
Nummer zwei kommt wohl dadurch zustande, dass die Parameter irgend wann einmal eben in Bytestrings gewandelt werden müssen - eben dann, wenn die Python-Welt verlassen wird. Und auch dabei wählt der Interpreter dann eben das Default-Encoding ASCII, wenn kein Script weites Encoding eingestellt ist.
Das ist ja aber nicht so.
Du setzt diesen Beispielstring übrigens ziemlich umständlich zusammen ;-)

Code: Alles auswählen

c_id3_author_value = u"Max" + " " + u"Müller"
# ist doch dassselbe wie:
c_id3_author_value = u"Max Müller"
Ursprünglich kommen die Daten aus Tabellenfeldern...
Danke für die Hinweise.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Hm... speicherst Du die Datei denn auch utf-8 codiert?

Und kannst Du nicht mal ein anderes Beispiel probieren, außer "lame"? Vielleicht ein "echo" oder so? Dann könnte man das ggf. mal lokal nachvollziehen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
pPilger
User
Beiträge: 45
Registriert: Montag 8. Februar 2010, 17:30

Hyperion hat geschrieben: Ich wette, dass einige der Strings im Popen args-Paratemer uneinheitlich sind, also einige Unicode, andere Bytestrings. Kann das sein?
Werd ich prüfen. Es knallt nur, wenn Umlaute vorkommen, sonst gehts prima.
Ja, es waren einige Argumente in unicode.
Nur zur Info: Ich bekomm jetzt zwar alles einheitlich "raus" indem ich jedes Argument mit dem gewünschten Zeichensatz encode:

Code: Alles auswählen

c_id3_title = u"--tt".encode( "Mein Zeichensatz" )
Aber der lame-encoder versteht offensichtlich kein utf-8...weshalb ich die nötigen Sonderzeichen in einer eigenen Routine ändere, da die mp3-Dateien später von utf-8 php-scripts wieterverarbeitet werden müssen...
Danke für die Hilfe.

Der Thread kann as gelößt betrachtet werden
Antworten