Python3 + Windows + subprocess + encoding?

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
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Welches encoding nimmt man wohl unter Windows um per subprocess korrektes unicode zu haben???

Code: Alles auswählen

encoding = sys.stdout.encoding or locale.getpreferredencoding()
ergibt hier: cp1252

Das sollte doch ok sein, oder?!?

Code: Alles auswählen

# encoding: utf-8

import sys, locale, os
import subprocess


print(sys.stdout.encoding)
print(sys.stdout.isatty())
print(locale.getpreferredencoding())
print(sys.getfilesystemencoding())

encoding = sys.stdout.encoding or locale.getpreferredencoding()

def run(*args, **kwargs):
    p = subprocess.Popen(args,
        stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
        **kwargs
    )
    return p.communicate()[0]

#~ output = run("cmd.exe", "/c", 'echo "abcäöüß"') # UnicodeDecodeError: 'charmap' codec can't decode byte 0x81 in position 7: character maps to <undefined>
output = run("mkdir", "/?", shell=True)
print(type(output))
print(repr(output))

output = output.decode(encoding)
print(repr(output))
print("nötig" in output)
Liefert bei mir in SciTE:

Code: Alles auswählen

cp1252
False
cp1252
mbcs
<class 'bytes'>
b'Erstellt ein Verzeichnis.\r\n\r\nMKDIR [Laufwerk:]Pfad\r\nMD    [Laufwerk:]Pfad\r\n\r\nWenn die Befehlserweiterungen aktiviert sind, wird MKDIR folgenderma\xe1en\r\nver\x84ndert:\r\n\r\nMKDIR erstellt, wenn n\x94tig, jedes Zwischenverzeichnis. Wenn zum\r\nBeispiel das Verzeichnis \\a nicht existiert, dann entspricht\r\n\r\n    mkdir \\a\\b\\c\\d\r\n\r\nder folgenden Befehlsfolge:\r\n\r\n    mkdir \\a\r\n    chdir \\a\r\n    mkdir b\r\n    chdir b\r\n    mkdir c\r\n    chdir c\r\n    mkdir d\r\n\r\nDiese Folge von Befehlen muss angegeben werden, wenn die Befehlserweiterungen \r\nnicht aktiviert sind.\r\n'
'Erstellt ein Verzeichnis.\r\n\r\nMKDIR [Laufwerk:]Pfad\r\nMD    [Laufwerk:]Pfad\r\n\r\nWenn die Befehlserweiterungen aktiviert sind, wird MKDIR folgendermaáen\r\nver„ndert:\r\n\r\nMKDIR erstellt, wenn n”tig, jedes Zwischenverzeichnis. Wenn zum\r\nBeispiel das Verzeichnis \\a nicht existiert, dann entspricht\r\n\r\n    mkdir \\a\\b\\c\\d\r\n\r\nder folgenden Befehlsfolge:\r\n\r\n    mkdir \\a\r\n    chdir \\a\r\n    mkdir b\r\n    chdir b\r\n    mkdir c\r\n    chdir c\r\n    mkdir d\r\n\r\nDiese Folge von Befehlen muss angegeben werden, wenn die Befehlserweiterungen \r\nnicht aktiviert sind.\r\n'
False
sys.stdout.encoding == cp1252 und das scheint falsch zu sein:

Der Test "nötig" in output ist False
In der Ausgabe ist es auch: b'...n\x94tig...' und nach dem decode(): '...n”tig...'

Wenn ich das ganze in cmd.exe laufen lasse, ist es ok:

Code: Alles auswählen

D:\>py test.py
cp850
True
cp1252
mbcs
<class 'bytes'>
b'Erstellt ein Verzeichnis.\r\n\r\nMKDIR [Laufwerk:]Pfad\r\nMD    [Laufwerk:]Pfad\r\n\r\nWenn die Befehlserweiterungen aktiviert sind, wird MKDIR folgenderma\xe1en\r\nver\x84ndert:\r\n\r\nMKDIR erstellt, wenn n\x94tig, jedes Zwischenverzeichnis. Wenn zum\r\nBeispiel das Verzeichnis \\a nicht existiert, dann entspricht\r\n\r\n    mkdir \\a\\b\\c\\d\r\n\r\nder folgenden Befehlsfolge:\r\n\r\n    mkdir \\a\r\n    chdir \\a\r\n    mkdir b\r\n    chdir b\r\n    mkdir c\r\n    chdir c\r\n    mkdir d\r\n\r\nDiese Folge von Befehlen muss angegeben werden, wenn die Befehlserweiterungen \r\nnicht aktiviert sind.\r\n'
'Erstellt ein Verzeichnis.\r\n\r\nMKDIR [Laufwerk:]Pfad\r\nMD    [Laufwerk:]Pfad\r\n\r\nWenn die Befehlserweiterungen aktiviert sind, wird MKDIR folgendermaßen\r\nverändert:\r\n\r\nMKDIR erstellt, wenn nötig, jedes Zwischenverzeichnis. Wenn zum\r\nBeispiel das Verzeichnis \\a nicht existiert, dann entspricht\r\n\r\n    mkdir \\a\\b\\c\\d\r\n\r\nder folgenden Befehlsfolge:\r\n\r\n    mkdir \\a\r\n    chdir \\a\r\n    mkdir b\r\n    chdir b\r\n    mkdir c\r\n    chdir c\r\n    mkdir d\r\n\r\nDiese Folge von Befehlen muss angegeben werden, wenn die Befehlserweiterungen \r\nnicht aktiviert sind.\r\n'
True
Der Unterschied ist, das jetzt sys.stdout.encoding == cp850 und das Ergebnis ist richtig.

Wenn ich es mit PyCharm laufen lasse, ist sys.stdout.encoding == None

Mit "cp850" Funktioniert auch die Zeile mit 'echo "abcäöüß"' korrekt.

Fazit: Encoding immer cp850 und gut?!?
SciTE und PyCharm machen mist, beim encoding des Terminals ?!?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

@jens: Man nimmt die Kodierung die vom Programm auf der anderen Seite erwartet wird. Welche das ist? Das muss man wissen oder ausprobieren. Und hoffen das man richtig geraten hat, oder immer dynamisch richtig rät und die Kodierung auf diese gleiche Weise ermittelt wie das andere Programm. Die Frage lässt sich also nicht allgemein beantworten.
Antworten