Python Popen无法在Windows PowerShell中使用正确的编码

时间:2012-04-03 11:33:14

标签: python powershell unicode mercurial

我在Windows PowerShell中运行我的Python脚本,脚本应该使用Popen运行另一个程序,然后管道该程序的输出(实际上是Mercurial)以便在我的脚本中使用。我尝试在PowerShell中执行脚本时收到编码错误。

我很确定它正在发生,因为在获取Popen调用的输出时,Python没有使用PowerShell正在使用的正确编码。 问题是我不知道如何告诉Python使用正确的编码。


我的脚本看起来像

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

当我在Linux上运行此脚本时,我没有任何问题。我也可以使用PowerShell在Windows 7 Home Premium 64位中运行该脚本,没有任何问题。此Windows 7中的PowerShell使用代码页850,即chcp的输出为850(“ibm850”)。

但是,当我使用PowerShell运行 Windows 7 Starter 32位中的脚本时,默认情况下编码为cp437(chcp = { {1}}),我从Python(版本2.7.2)收到以下错误:

437

我尝试过以下操作,但没有成功(即上述错误报告保持不变):

  • 从我的脚本中删除行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
  • 在我的脚本中删除通过Popen运行Mercurial的# -*- coding: utf-8 -*-选项。
  • 在执行我的脚本之前,将编码更改为PowerShell中的-- encoding UTF-8
  • 我在其他Stack Overflow答案中发现了许多其他杂项Python黑客。

对于我的具体细节,我的整个源代码可用here in BitBucketchcp 850是提供错误的脚本。


更新 这个脚本由other script调用,它正在设置这样的编码

hgapi.py

这一行看起来很重要,因为如果我发表评论,我会得到一个不同的错误:

sys.setdefaultencoding("utf-8")

2 个答案:

答案 0 :(得分:2)

尝试将编码更改为cp1252。 Windows中的Popen希望shell命令编码为cp1252。这似乎是一个错误,它似乎也通过subprocess模块在​​Python 3.X中修复:http://docs.python.org/library/subprocess.html

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

<强>更新

您的问题可以通过Django模块的 smart_str 功能解决。

使用此代码:

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)

您可以在Windows here上找到有关如何安装Django的信息。 您可以先安装pip,然后再开始安装Django 具有管理员权限的命令shell并运行此命令:

pip install Django

这将在您的Python安装的site-packages目录中安装Django。

答案 1 :(得分:1)

使用from __future__ import unicode_literals后,我开始收到相同的错误,但是在代码的不同部分:

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

给出错误

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

确实,x是一个字节字符串,其中包含\xe3(在cp1252中为ã)。因此,我使用x.decode('utf-8')而不是使用x.decode('windows-1252'),而且没有给我任何错误。为了支持任何类型的编码,我最终使用了x.decode(sys.stdout.encoding)问题解决了。

这是在使用Windows 7 Starter计算机的Python 3.2.2中,但同一台计算机上的Python 2.7也能正常工作。