Windows 在 subprocess.call() 上找不到文件
Posted
技术标签:
【中文标题】Windows 在 subprocess.call() 上找不到文件【英文标题】:Windows can't find the file on subprocess.call() 【发布时间】:2011-03-02 14:37:54 【问题描述】:我收到以下错误:
WindowsError: [Error 2] The system cannot find the file specified
我的代码是:
subprocess.call(["<<executable file found in PATH>>"])
Windows 7、64 位。 Python 3.x 最新、稳定。
有什么想法吗?
谢谢,
【问题讨论】:
这个可执行文件是什么? android SDK 的“android”可执行部分 并且 is 在 PATH 上可用 可以从命令行运行吗? 我想要完成的事情的一点背景。这适用于 Opendevice - 一个将 html5 应用程序转换为特定于设备的应用程序的开源项目。我正在尝试将bitbucket.org/srirangan/opendevice/src/tip/tools/net/srirangan/… 中的 os.system() 替换为 subprocess.call() 【参考方案1】:当命令是内置的 shell 时,在调用中添加 shell=True
。
例如对于dir
,您可以输入:
import subprocess
subprocess.call('dir', shell=True)
引用documentation:
您需要在 Windows 上指定
shell=True
的唯一情况是当您希望执行的命令内置到 shell 中时(例如 dir 或 copy)。您不需要shell=True
来运行批处理文件或基于控制台的可执行文件。
【讨论】:
这是因为在 *nix 中没有名为dir.exe
的可执行文件,而有一个 /bin/ls
。 dir
由 CMD.EXE 实现,就像cd
由 bash 实现。
强烈建议不要这样做。 docs.python.org/2/library/…
@nueverest 仅当命令字符串是从外部输入构造的
另一种选择(对于外部输入更安全)是从os.environ
获取PATH
并手动搜索。【参考方案2】:
在 Windows 上,我相信 subprocess
module doesn't look in the PATH
unless you pass shell=True
,因为它在幕后使用 CreateProcess()
。但是,如果您传递的参数可能来自程序外部,shell=True
可能会带来安全风险。要使subprocess
仍然能够找到正确的可执行文件,您可以使用shutil.which
。假设您的PATH
中的可执行文件名为frob
:
subprocess.call([shutil.which('frob'), arg1, arg2])
(这适用于 Python 3.3 及更高版本。)
【讨论】:
任何 python 2 选项? @Naramsim 试试from distutils.spawn import find_executable as which
。此行是从 pre-commit 的钩子脚本中复制的。【参考方案3】:
在 Windows 上,您必须通过 cmd.exe 调用。正如 Apalala 所说,Windows 命令是在 cmd.exe 中实现的,而不是作为单独的可执行文件。
例如
subprocess.call(['cmd', '/c', 'dir'])
/c 告诉 cmd 运行以下命令
这比使用 shell=True 更安全,后者允许 shell 注入。
【讨论】:
如何保持屏幕打开? @Moondra,如果我理解正确,请尝试使用/k
而不是/c
。在命令行输入cmd /?
了解详情。【参考方案4】:
如果您使用的是 powershell,那么其中将是 subprocess.call(['powershell','-command','dir'])
。 Powershell 支持大部分 POSIX 命令
【讨论】:
【参考方案5】:经过一番摸索,我发现在 64 位机器上运行 32 位版本的 python 时运行位于 C:\Windows\System32\ 中的文件是一个潜在问题,因为 Windows 试图超越进程,并将对 C:\Windows\System32 的调用重定向到 C:\Windows\SysWOW64。
我在这里找到了如何解决此问题的示例: http://code.activestate.com/recipes/578035-disable-file-system-redirector/
【讨论】:
【参考方案6】:引用文档:
“在 Python 3.5 之前,这三个函数构成了用于子进程的高级 API。现在您可以在许多情况下使用 run(),但是很多现有代码都会调用这些函数。”
SO:在 Python 3.5 及更高版本中使用 subprocess.run 代替 subprocess.call
【讨论】:
这是一个很好的建议本身,但没有解决这里的实际问题。【参考方案7】:我在调用 php 时遇到了同样的问题。原因是 PHP 不在 PATH 中,因此找不到命令 PHP。但是 PowerShell 发现它确实存在于当前位置,如果我相信这个命令,它建议用 '.\PHP' 替换 'PHP'。然后它运行良好。
【讨论】:
以上是关于Windows 在 subprocess.call() 上找不到文件的主要内容,如果未能解决你的问题,请参考以下文章
Python subprocess.call 打不开 Notepad.exe?