Windows上使用Python和subprocess.Popen()的Unicode文件名

Nor*_*man 12 python windows unicode

为什么会发生以下情况:

>>> u'\u0308'.encode('mbcs')   #UMLAUT
'\xa8'
>>> u'\u041A'.encode('mbcs')   #CYRILLIC CAPITAL LETTER KA
'?'
>>>
Run Code Online (Sandbox Code Playgroud)

我有一个Python应用程序接受操作系统的文件名.它适用于一些国际用户,但不适用于其他用户.

例如,这个unicode文件名:u'\ u041a\u0433\u044b\u044b\u0448\u0444\u0442'

不会使用Windows的'mbcs'编码进行编码(文件系统使用的编码,由sys.getfilesystemencoding()返回).我得到'???????',表示编码器在这些字符上失败.但这没有任何意义,因为文件名来自用户开始.

更新:这是我背后原因的背景...我的系统上有一个文件,名字是西里尔文.我想用该文件作为参数调用subprocess.Popen().Popen不会处理unicode.通常情况下,我可以使用sys.getfilesystemencoding()给出的编解码器对参数进行编码.在这种情况下,它将无法正常工作

kxr*_*kxr 8

在Py3K中 - 至少从Python 3.2开始 - subprocess.Popensys.argv在Windows上与(默认的unicode)字符串一致地工作.CreateProcessWGetCommandLineW明显使用.

在Python中 - 至少达到v2.7.2 - subprocess.Popen对于Unicode参数来说是错误的.它坚持CreateProcessA(虽然os.*与Unicode一致).并shlex.split创造了额外的废话.

Pywin32 win32process.CreateProcess也没有自动切换到W版本,也没有win32process.CreateProcessW.与...相同GetCommandLine.因此ctypes.windll.kernel32.CreateProcessW...需要使用.对于这个问题,可能应修复子进程模块.

argv[1:]使用私有应用程序的UTF8在Unicode操作系统上仍然很笨拙.对于像Linux这样的8位"Latin1"字符串操作系统来说,这样的技巧可能是合法的.

UPDATE vaab Popen为Python 2.7 创建了一个补丁版本,修复了这个问题.
请参阅https://gist.github.com/vaab/2ad7051fc193167f15f85ef573e54eb9
博客文章及解释:http://vaab.blog.kal.fr/2017/03/16/fixing-windows-python-2-7-unicode-issue -with-subprocesss-POPEN /


vaa*_*aab 5

免责声明:我是以下提到的修复的作者.

为支持Unicode命令行窗口与Python 2.7,你可以使用 这个补丁subprocess.Popen(..)

情况

Python 2对Windows上的unicode命令行的支持非常差.

严重错误:

  • 从调用方(通过subprocess.Popen(..))向系统发出unicode命令行,

  • 并从被调用方(通过sys.argv)读取当前命令行unicode参数,

它被承认并且不会在Python 2上修复.这些在Python 3中得到修复.

技术原因

在Python 2中,windows实现subprocess.Popen(..)sys.argv使用非unicode就绪的windows系统调用CreateProcess(..)(参见python 代码CreateProcess的 MSDN doc)并且不GetCommandLineW(..)用于sys.argv.

在Python 3,Windows实现的subprocess.Popen(..)利用正确的Windows系统调用CreateProcessW(..)从开始3.0(见代码3.0),并sys.argv采用GetCommandLineW(..)从开始3.3(见代码3.3).

它是如何修复的

给定的补丁将利用ctypes模块CreateProcessW(..)直接调用C windows系统.它提出了一个新的固定Popen对象,它通过重写私有方法Popen._execute_child(..)和私有函数_subprocess.CreateProcess(..)来设置和使用CreateProcessW(..)来自windows系统lib,其方式尽可能地模仿它在Python中的运行方式3.6.

如何使用它

博文的解释说明了如何使用给定的补丁.它还显示了如何sys.argv使用另一个修复程序读取当前进程 .


Joh*_*hin 3

sys.getfilesystemencoding() 的文档说,对于 Windows NT 及更高版本,文件名本身就是 Unicode。如果您有有效的 unicode 文件名,为什么还要使用 mbcs 对其进行编码呢?

编解码器模块的文档说 mbcs 使用“ANSI 代码页”进行编码(根据用户的区域设置而有所不同),因此如果区域设置不使用西里尔字符,则 splat。

编辑:所以你的进程正在调用 subprocess.Popen()。如果您调用的进程在您的控制之下,则两个进程应该能够同意使用 UTF-8 作为 Unicode 传输格式。否则,您可能需要在 pywin32 邮件列表上询问。无论如何,编辑您的问题以说明您对调用的流程的控制程度。