Python Popen未能在Windows PowerShell中使用正确的编码

Python Popen未能在Windows PowerShell中使用正确的编码,python,powershell,unicode,mercurial,Python,Powershell,Unicode,Mercurial,我正在Windows PowerShell中运行Python脚本,该脚本应该使用Popen运行另一个程序,然后通过管道将该程序的输出(实际上是Mercurial)用于我的脚本。尝试在PowerShell中执行脚本时,出现编码错误 我很确定这是因为Python在获取Popen调用的输出时没有使用PowerShell使用的正确编码问题是我不知道如何告诉Python使用正确的编码。 我的脚本看起来像 # -*- coding: utf-8 -*- #... some imports proc = P

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

我很确定这是因为Python在获取Popen调用的输出时没有使用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”)

然而当我使用默认编码为cp437(
chcp
=
437
)的PowerShell在Windows 7 Starter 32位运行脚本时,我从Python(版本2.7.2)中得到以下错误:

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

  • 从我的脚本中删除行
    #-*-coding:utf-8-*-
  • 删除脚本中通过Popen运行Mercurial的
    --encoding UTF-8
    选项
  • 在执行我的脚本之前,在PowerShell中将编码更改为
    chcp 850
  • 我在其他堆栈溢出答案中发现了许多其他杂项Python攻击
对于我的具体细节,我的全部源代码都是可用的
hgapi.py
是给出错误的脚本


更新: 该脚本正在被调用,其编码设置如下

sys.setdefaultencoding("utf-8")
这一行看起来很重要,因为如果我把它注释掉,我会得到一个不同的错误:

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

尝试将编码更改为
cp1252
。Windows中的Popen希望shell命令编码为
cp1252
。这似乎是一个bug,在Python 3.X中,它似乎通过
子流程
模块得到了修复:

更新:

您的问题可能可以通过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上安装Django的信息。 您可以先安装,然后通过启动来安装Django 具有管理员权限的命令shell,并运行此命令:

pip install Django

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

在使用来自“未来”的“导入unicode”文本的
后,我开始出现相同的错误,但代码的不同部分:

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')
,这没有给我带来任何bug。为了支持任何类型的编码,我最终使用了
x.decode(sys.stdout.encoding)
问题已解决。


这是在装有Windows 7 Starter计算机的Python 3.2.2中实现的,但同一台计算机上的Python 2.7也正常工作。

通过什么将编码更改为cp1252
chcp 1252
在PowerShell中没有帮助。@STALTZ Try
$outpuneCoding=[控制台]::outpuneCoding
@STALTZ很抱歉,也许我更新的答案可以帮助您,但您必须安装一个新模块,即django
smart_str
是一个非常有用的函数。您可以在这里找到更多信息:我还没有尝试过您的Django解决方案@ThanasisPetsas,因为我认为应该有一些基本的Python解决方案。无论如何,谢谢,如果我没有找到其他解决方案,我最终可以使用Django。当使用时,您是否也有同样的问题?因为您使用的是python,所以看起来很自然。该项目以前使用mercurial内部api,但我改用命令行api,因为这是官方的稳定api。除了扩展之外,不应使用内部api。这更像是
args
数组的问题,因为在
list2cmdline
中引发了异常。可能
args
self.path
是字节字符串而不是Unicode字符串?在Windows上,通常希望尽可能使用Unicode字符串
hgapi.py
将所有字符串文字转换为Unicode文字(
来自uuu未来uuu导入Unicode_u文字
),而
hypergrasscore.py
可能也会这样做。@Philipp,这很有意义。但是,我添加了来自uuu future uuuu导入unicode u文本的
,仍然得到相同的错误。事实上,我甚至在调用hgapi.py的hypergrasscore.py脚本中的字符串(
u'string'
)之前包含了
u
,但没有成功=/有趣-在我的例子中,
sys.stdout.encoding
没有-locale.getpreferredencoding()会起作用吗?
out, err = [x.decode("utf-8") for x in  proc.communicate()]
UnicodeDecodeError: 'utf8' codec cant decode byte 0xe3 in position 33 ....