Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Python的Windows上的Unicode文件名&;subprocess.Popen()_Python_Windows_Unicode - Fatal编程技术网

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

使用Python的Windows上的Unicode文件名&;subprocess.Popen(),python,windows,unicode,Python,Windows,Unicode,为什么会出现以下情况: >>> u'\u0308'.encode('mbcs') #UMLAUT '\xa8' >>> u'\u041A'.encode('mbcs') #CYRILLIC CAPITAL LETTER KA '?' >>> 我有一个Python应用程序接受来自操作系统的文件名。它适用于一些国际用户,但不适用于其他用户 例如,此unicode文件名: u'\u041a\u0433\u044b\u044b\u0448\

为什么会出现以下情况:

>>> 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.getfilesystemencoding()返回)。我得到“??”,表示编码器在这些字符上失败。但这毫无意义,因为文件名一开始就来自用户

更新:以下是我的背景,我的理由背后。。。
我的系统中有一个文件名为西里尔文。我想用该文件作为参数调用subprocess.Popen()。Popen无法处理unicode。通常,我可以使用sys.getfilesystemencoding()给出的编解码器对参数进行编码。在这种情况下,如果说对于Windows NT和更高版本,文件名本机是Unicode,那么它将不起作用。如果您有一个有效的unicode文件名,为什么还要麻烦使用mbcs对其进行编码

假设mbcs使用“ANSI代码页”(根据用户的区域设置而有所不同)进行编码,因此如果区域设置不使用西里尔字符,请使用splat


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

如果您需要传递现有文件的名称,则通过传递8.3版本的Unicode文件名可能会有更好的成功机会

您需要安装软件包,然后可以执行以下操作:

>>> import win32api
>>> win32api.GetShortPathName(u"C:\\Program Files")
'C:\\PROGRA~1'
我相信这些短文件名只使用ASCII字符,因此您应该能够将它们用作命令行的参数

如果还需要指定要创建的文件名,可以使用Unicode文件名从Python中提前创建零大小的文件名,并将文件的短名称作为参数传递


更新:用户bogdan正确地说8.3文件名生成可以被禁用(我在笔记本电脑上安装Windows XP时也禁用了它),所以你不能依赖它们。因此,在处理NTFS卷时,另一种更为牵强的方法是,可以将Unicode文件名转换为普通ASCII文件名;将ASCII文件名传递给外部命令,然后将其删除。

在Py3K中-至少从Python 3.2-
子流程中。Popen
sys.argv
与Windows上的(默认unicode)字符串一致
CreateProcessW
GetCommandLineW
被明显使用

在Python-v2.7.2之前的版本中,至少-
subprocess.Popen
带有Unicode参数。它坚持使用
CreateProcessA
(而
os.*
与Unicode一致)。而shlex.split会产生额外的废话

Pywin32的
win32process.CreateProcess
也不会自动切换到W版本,也没有
win32process.CreateProcessW
。与
GetCommandLine
相同。 因此,需要使用
ctypes.windl.kernel32.CreateProcessW…
。 关于此问题,子流程模块可能应该得到修复

在Unicode操作系统上,带有私有应用的
argv[1:://code>上的UTF8仍然很笨拙。对于像Linux这样的8位“Latin1”字符串操作系统,这些技巧可能是合法的

更新vaab为Python 2.7创建了一个修补版的
Popen
,解决了这个问题。


带有解释的博客帖子:

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

要在带有python 2.7的windows上支持unicode命令行,可以使用 到
subprocess.Popen(..)

形势

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

被严重窃听:

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

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

在Python2上,这是公认的。这些在Python3中是固定的

技术原因

在Python2中,
subprocess.Popen(…)
sys.argv
的windows实现使用非unicode就绪的windows系统调用
CreateProcess(…)
(请参见Python和MSDN),而不对
sys.argv
使用
GetCommandLineW(…)

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

它是如何固定的

给定的将利用
ctypes
模块调用C窗口 系统
直接创建进程w(..)
。它提出了一个新的固定的
Popen
对象,通过覆盖私有方法
Popen.\u执行子(…)
和私有函数
\u子流程.CreateProcess(…)
从windows系统库中设置和使用
CreateProcessW(…)
,尽可能模仿Python
3.6
中的操作方式

如何使用它

下面将演示如何使用给定的补丁。它还显示了如何读取当前进程
sys.argv
with.

对于Python3,只需不编码字符串即可。Windows文件名本机为Unicode,Python 3中的所有字符串均为Unicode,Popen使用Unicode版本的
CreateProcess
Windows API函数

使用Python2.7