2012-04-03 5 views
3

Ich verwende mein Python-Skript in Windows PowerShell, und das Skript sollte ein anderes Programm mit Popen ausführen, dann die Ausgabe dieses Programms (Mercurial, eigentlich) für die Verwendung in meinem Skript pipe . Ich erhalte einen Kodierungsfehler, wenn ich versuche, mein Skript in PowerShell auszuführen.Python Popen nicht ordnungsgemäß Codierung in Windows PowerShell

Ich bin ziemlich sicher, dass es passiert, weil Python nicht die richtige Codierung verwendet, die PowerShell verwendet, wenn die Ausgabe des Popen-Aufrufs abgerufen wird. Das Problem ist, dass ich nicht weiß, wie ich Python die korrekte Kodierung mitteilen soll.


Mein Skript sieht aus wie

# -*- coding: utf-8 -*- 
#... some imports 
proc = Popen(["hg", "--cwd", self.path, "--encoding", "UTF-8"] + list(args), stdout=PIPE, stderr=PIPE) 
#... other code 

Als ich das Skript auf Linux laufen, ich überhaupt keine Probleme haben. Ich kann das Skript auch in Windows 7 Home Premium 64-Bit mit PowerShell ohne Probleme ausführen. Die PowerShell in diesem Windows 7 verwendet die Codepage 850, dh die Ausgabe von chcp ist 850 ("ibm850").

jedoch, wenn ich das Skript in einem Windows 7 Starter 32-Bit laufe eine Powershell verwenden, die die Codierung CP437 hat in der Standardeinstellung (chcp = 437), erhalte ich die folgende Fehlermeldung von Python (Version 2.7. 2):

File "D:\Path\to\myscript.py", line 55, in hg_command 
    proc = Popen(["hg", "--cwd", self.path, "--encoding", "UTF-8"] + list(args), stdout=PIPE, stderr=PIPE) 
File "C:\Program files\Python27\lib\subprocess.py", line 679, in __init__ 
    errread, errwrite) 
File "C:\Program files\Python27\lib\subprocess.py", line 852, in _execute_child 
    args = list2cmdline(args) 
File "C:\Program files\Python27\lib\subprocess.py", line 615, in list2cmdline 
    return ''.join(result) 
UnicodeDecodeError: 'utf8' codec cant decode byte 0xe3 in position 0: unexpected end of data 

ich folgendes probiert, ohne Erfolg (dh der oben genannten Fehlerbericht bleibt gleich):

  • entfernen Sie die Zeile 012.326.von meinem Skript.
  • Entfernen Sie die -- encoding UTF-8 Option zum Ausführen von Mercurial durch Popen in meinem Skript.
  • Ändern Sie die Codierung in PowerShell in chcp 850, bevor Sie mein Skript ausführen.
  • Viele andere verschiedene Python-Hacks habe ich in anderen Stack Overflow Antworten gefunden.

Für meine spezifischen Details ist mein gesamter Quellcode verfügbar here in BitBucket. hgapi.py ist das Skript, das den Fehler gibt.


UPDATE: Das Skript von diesem other script genannt wird, die die Codierung wie diese

sys.setdefaultencoding("utf-8") 

setzt Diese Zeile sieht wichtig, denn wenn ich es auf Kommentar, ich bekommen anderer Fehler:

UnicodeDecoreError: 'ascii' codec cant decode byte 0xe3 in position 0: ordinal not in range(128) 
+0

Haben Sie das gleiche Problem bei der Verwendung der [mercurial api] (http://mercurial.selenic.com/wiki/MercurialApi)? Da Sie Python verwenden, scheint es wie eine natürliche Passform. –

+1

Das Projekt verwendete die mercuriale interne API, aber ich wechselte zur Befehlszeile api, weil das das offizielle stabile ist. Die interne API darf nur für Erweiterungen verwendet werden. –

+0

Das sieht eher wie ein Problem mit dem 'args' Array aus, da die Ausnahme in' list2cmdline' ausgelöst wird. Vielleicht ist 'args' oder' self.path' eine Byte-Zeichenfolge anstelle einer Unicode-Zeichenfolge? – Philipp

Antwort

1

Nach from __future__ import unicode_literals mit Ich begann die gleichen Fehler, aber in einem anderen Teil des Codes:

out, err = [x.decode("utf-8") for x in proc.communicate()] 

gab den Fehler

UnicodeDecodeError: 'utf8' codec cant decode byte 0xe3 in position 33 .... 

Tatsächlich x war ein Bytestring mit \xe3 (das ist in cp1252) enthalten. Anstatt also x.decode('utf-8') zu verwenden, habe ich x.decode('windows-1252') verwendet und das gab mir keine Fehler. Um jede Art von Codierung zu unterstützen, verwendete ich stattdessen x.decode(sys.stdout.encoding). Problem gelöst.

Und das war in Python 3.2.2 mit dem Windows 7 Starter-Computer, aber Python 2.7 auf dem gleichen Computer funktionierte auch normal.

+0

Interessant - in meinem Fall http://stackoverflow.com/questions/28101187/deal-withunicode-usernames-in-python-mkdtemp 'sys.stdout.encoding' ist keine - würde locale.getpreferredencoding() den Trick tun ? –

2

Versuchen Sie, die Codierung in cp1252 zu ändern. Popen in Windows möchte Shell-Befehle, die als cp1252 codiert sind. Dies scheint wie ein Fehler zu sein, und es scheint auch in Python 3 behoben zu sein.X durch das subprocess Modul: http://docs.python.org/library/subprocess.html

import subprocess 
subprocess.Popen(["hg", "--cwd", self.path, "--encoding", "UTF-8"] + list(args), stdout=PIPE, stderr=PIPE) 

Update:

Ihr Problem kann vielleicht durch smart_str Funktion von Django Modul gelöst werden.

Mit diesem Code:

from django.utils.encoding import smart_str, smart_unicode 
# the cmd should contain sthe string with the commsnd that you want to execute 
smart_cmd = smart_str(cmd) 
subprocess.Popen(smart_cmd) 

Sie Informationen finden, wie Django unter Windows here zu installieren. Sie können zunächst pip installieren und dann können Sie Django installieren ein Kommando-Shell mit Administratorrechten starten und diesen Befehl ausführen:

pip install Django 

Diese Django installieren in Ihrer Website-Pakete-Verzeichnis der Python-Installation.

+0

Ändern Sie die Codierung zu cp1252 durch was? 'chcp 1252' in PowerShell hilft nicht. –

+0

Erzeugt es die gleichen Fehler? –

+0

@STALTZ Try '$ OutputEncoding = [Konsole] :: OutputEncoding' –

Verwandte Themen