在Windows平台上使用Python和subprocess.Popen()处理Unicode文件名

2024-05-02 19:51:48 发布

您现在位置:Python中文网/ 问答频道 /正文

为什么会出现以下情况:

>>> u'\u0308'.encode('mbcs')   #UMLAUT
'\xa8'
>>> u'\u041A'.encode('mbcs')   #CYRILLIC CAPITAL LETTER KA
'?'
>>>

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

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

不会使用Windows“mbcs”编码(文件系统使用的编码,由sys.getFileSystemCoding()返回)。我明白了,表示编码器在这些字符上失败。但这毫无意义,因为文件名是从用户开始的。

更新:这是我背后的原因背景。。。 我的系统中有一个用西里尔文命名的文件。我想用那个文件作为参数调用subprocess.Popen()。Popen不能处理unicode。通常,我可以使用sys.getFileSystemCoding()提供的编解码器对参数进行编码。在这种情况下是行不通的


Tags: 文件用户编码参数文件名sysunicode情况
3条回答

在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...。 关于这个问题,可能应该修复子流程模块。

在Unicode操作系统上,使用私有应用程序的UTF8仍然很笨拙。对于像Linux这样的8位“Latin1”字符串操作系统,这样的技巧可能是合法的。

更新vaab为Python 2.7创建了Popen的修补版本,该版本修复了该问题。
https://gist.github.com/vaab/2ad7051fc193167f15f85ef573e54eb9
有解释的博客文章:http://vaab.blog.kal.fr/2017/03/16/fixing-windows-python-2-7-unicode-issue-with-subprocesss-popen/

免责声明:我是下面提到的修复程序的作者。

要在带有Python2.7的windows上支持unicode命令行,可以使用 this patchsubprocess.Popen(..)

情况

Python 2在windows上对unicode命令行的支持非常差。

被严重窃听:

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

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

它在Python 2上被确认并won't be fixed。这些在Python 3中是固定的。

技术原因

在Python 2中,subprocess.Popen(..)sys.argv的windows实现使用非unicode就绪的windows系统调用CreateProcess(..)(请参见Pythoncode,和MSDNdoc of CreateProcess),而不使用GetCommandLineW(..)来获取sys.argv

在Python 3中,subprocess.Popen(..)的windows实现使用正确的windows系统调用CreateProcessW(..)3.0开始(请参见3.0中的^{GetCommandLineW(..)从3.3开始(请参见3.3中的^{

如何修复

给定的patch将利用ctypes模块调用C窗口 直接系统CreateProcessW(..)。它通过重写私有方法Popen._execute_child(..)和私有函数_subprocess.CreateProcess(..)从windows系统库中设置和使用CreateProcessW(..),提出了一个新的固定Popen对象,以尽可能模拟在Python中的工作方式3.6

如何使用它

如何使用给定的修补程序将通过blog post explanation演示。它还显示了如何读取当前进程 sys.argvanother fix一起。

Docs for sys.getfilesystemencoding()假设对于Windows NT和更高版本,文件名本机是Unicode。如果您有一个有效的unicode文件名,为什么还要用mbcs编码呢?

Docs for codecs module假设mbcs使用“ANSI代码页”(根据用户的语言环境而不同)进行编码,因此如果语言环境不使用西里尔字符,请splat。

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

相关问题 更多 >