【问题标题】:subprocess.Popen with a unicode pathsubprocess.Popen 带有 unicode 路径
【发布时间】:2012-04-14 00:37:14
【问题描述】:

我想打开一个 unicode 文件名。 以下代码:

cmd = u'cmd /c "C:\\Pok\xe9mon.mp3"'
cmd = cmd.encode('utf-8')
subprocess.Popen(cmd)

返回

>>> 'C:\Pokיmon.mp3' is not recognized as an internal or external command, operable program or batch file.

即使该文件确实存在。为什么会这样?

【问题讨论】:

  • 我认为 'cmd' 代表别的东西?
  • 我删除了双引号,即使它们与问题无关。
  • 您是否已将 python 路径包含在您的 PATH 环境变量中?假设你的 Python 安装在 C:\Python25 中,你的新路径变量应该是:%PATH%;C:\Python25
  • 是的,但PATH 与什么有什么关系?

标签: python windows unicode command-line subprocess


【解决方案1】:

我认为 windows 使用 16 位字符,不确定它是 UCS2 还是 UTF16 或类似的东西。所以我猜它可能与 UTF8 有问题。

【讨论】:

  • 设置为 'utf-16' 返回 TypeError: must be string without null bytes or None, not str 所以我猜那是错误的。
【解决方案2】:

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

使用此代码:

from django.utils.encoding import smart_str, smart_unicode
cmd = u'cmd /c "C:\\Pok\xe9mon.mp3"'
smart_cmd = smart_str(cmd)
subprocess.Popen(smart_cmd)

您可以找到有关如何在 Windows here 上安装 Django 的信息。 可以先安装pip,然后启动安装Django 具有管理员权限的命令外壳并运行以下命令:

pip install Django

这会将 Django 安装到 Python 安装的 site-packages 目录中。

【讨论】:

  • 我不会为了正确编码 unicode 而安装一个全新的框架。 fix 应该是一两行,而不是 1000+ 的复杂代码。
  • 好的,对不起,我已经更新了我的答案。也许现在更有帮助。
  • 首先,latin-1 编码不是 unicode。它不适用于所有 unicode 案例。第二,还是不行。自己试试吧。
  • 好的,我在 Linux 上工作,我用os.popen 对其进行了测试,它可以工作。也许对于 Windows 不起作用.. :( 我删除了答案的更新部分。
  • 有人用 Django smart_str 制作了一个独立的模块:smartencoding
【解决方案3】:
>>> subprocess.call(['start', u'avión.mp3'.encode('latin1')], shell=True)
0

如果您使用shell 参数,则无需调用cmd 启动关联程序的正确方法是使用 cmd 的 start 内置 AFAIK。

我的 2c,嗨。

【讨论】:

  • 感谢旁注,但这仍然不能解决 unicode 问题。这适用于您的系统,因为您的语言环境 MBCS 具有 ó 字符。此代码不适用于以希伯来语或日语作为区域设置语言的计算机。
【解决方案4】:

看起来您使用的是 Windows 和 Python 2.X。使用os.startfile

>>> import os
>>> os.startfile(u'Pokémon.mp3')

不直观地,让命令 shell 做同样的事情是:

>>> import subprocess
>>> import locale
>>> subprocess.Popen(u'Pokémon.mp3'.encode(locale.getpreferredencoding()),shell=True)

在我的系统上,命令 shell (cmd.exe) 编码是 cp437,但对于 Windows 程序是 cp1252Popen 想要编码为 cp1252 的 shell 命令。这似乎是一个错误,在 Python 3.X 中似乎也已修复:

>>> import subprocess
>>> subprocess.Popen('Pokémon.mp3',shell=True)

【讨论】:

  • 谢谢!我不知道os.startfile
  • 在 Python 2 上的 Windows 上,Popen(u'Pokémon.mp3'.encode(encoding)) 工作 iff Popen(u'Pokémon.mp3'.encode('mbcs')) 工作,即它应该成功使用 cp1252 并且它应该失败 cp437 在你的情况下。 shell=True 会改变它吗? sys.getfilesystemencoding()locale.getpreferredencoding() 的值是什么?通常,u"é" 可能无法使用 mbcs 表示。 Python 3 直接使用 Unicode API。
  • 在python 2上的windows上,如果你想使用unicode命令行(如python 3),你可以使用this workaround利用ctypes修补subprocess.Popen(..)
  • os.startfile 有效,但u'Pokémon.mp3'.encode(locale.getpreferredencoding()) 在任何 ANSI 代码页未映射“é”的语言环境中当然会失败。在 2.x 中,subprocess.Popen 调用 CreateProcessA,它将命令行解码为 ANSI,因此它仅限于可以这样编码的命令。如果您需要一个不能编码为 ANSI 的命令行,那么您必须通过 ctypes、cffi 或扩展模块执行其他操作,例如调用 CreateProcessW 或 CRT 函数(例如 _wsystem)。
  • CMD 是一个 Unicode 应用程序。它仅在处理文件和管道时使用代码页来解码字节,例如读取批处理脚本的一行或从命令读取标准输出的for /f 循环。在这种情况下,如果它没有连接到控制台,它的默认代码页是 ANSI。否则,它使用 控制台的 输入或输出代码页(CMD 不是控制台),除非通过 chcp.com 更改,否则默认为 OEM。在任何情况下,CMD 用于文件的编码都是无关紧要的。当 CMD 看到它的命令行时,它已经被 Windows 解码为 Unicode。
猜你喜欢
  • 2011-01-24
  • 2013-07-03
  • 1970-01-01
  • 2014-04-23
  • 2016-04-10
  • 2014-02-20
  • 1970-01-01
  • 2013-05-16
  • 1970-01-01
相关资源
最近更新 更多