Windows在subprocess.call()函数中找不到文件。

14 浏览
0 Comments

Windows在subprocess.call()函数中找不到文件。

我遇到了以下错误:

WindowsError: [Error 2] 系统找不到指定的文件

我的代码是:

subprocess.call(["<<在PATH中找到的可执行文件>>"])

Windows 7,64位。Python 3.x最新稳定版。

有什么想法吗?

谢谢,

0
0 Comments

在Windows系统上,使用subprocess模块时,如果不传递shell=True参数,它不会在PATH环境变量中查找可执行文件。这是因为subprocess模块在后台使用CreateProcess()函数。然而,如果你从程序外部传递参数,使用shell=True参数可能存在安全风险。为了让subprocess模块能够找到正确的可执行文件,可以使用shutil.which函数。假设你的PATH环境变量中存在一个名为frob的可执行文件,你可以这样使用subprocess.call函数调用它:

subprocess.call([shutil.which('frob'), arg1, arg2])

(这个方法适用于Python 3.3及以上版本)

有没有适用于Python 2的方法呢?可以尝试使用from distutils.spawn import find_executable as which。这行代码是从pre-commit的钩子脚本中复制过来的。

然而,上述说法是不正确的。即使不使用shell=True参数,系统仍会检查PATH环境变量。但是,shell内置命令(如cd和dir)不在PATH中,因为它们根本不是可执行文件。这就是内置于shell中的含义;这些命令由shell自身理解和执行,不存在作为单独的二进制文件。

0
0 Comments

在Windows系统中,如果想要调用命令行操作,需要通过cmd.exe来实现。因为Windows的命令是在cmd.exe中实现的,而不是作为单独的可执行文件存在。

举个例子,如果想要在Python中调用dir命令,可以使用以下代码:

subprocess.call(['cmd', '/c', 'dir'])

其中,/c参数告诉cmd.exe要运行后面的命令。

这种方式相对于使用shell=True更安全,因为shell=True允许进行shell注入攻击。

如果想要保持命令行窗口打开,可以尝试使用/k参数而不是/c。在命令行中输入cmd /?可以查看更多详情。

当在Windows 10上使用powershell时,如果遇到WinError 5权限被拒绝的错误,以上的方法也可以帮助解决。

上述的方法其实是间接实现了shell=True的效果,但更加安全可靠。

0
0 Comments

Windows在使用subprocess.call()函数时无法找到文件的原因是由于Windows系统下的命令是内置的命令,而不是一个可执行文件。因此,需要在调用中添加shell=True参数。例如,对于dir命令,可以这样写:

import subprocess
subprocess.call('dir', shell=True)

根据官方文档(链接)的解释:

只有在需要执行的命令是shell内置命令(例如dircopy)时,才需要在Windows上指定shell=True。如果要运行批处理文件或基于控制台的可执行文件,则不需要使用shell=True

这是因为在Windows系统中没有名为dir.exe的可执行文件,而*nix系统中有一个/bin/ls。在Windows中,dir是由CMD.EXE实现的,类似于bash实现了cd

然而,这种做法是不被推荐的。根据官方文档(链接)的建议,只有在“命令字符串是由外部输入构造的”情况下才应使用shell=True参数。对于外部输入,更安全的替代方法是从os.environ中获取PATH并手动搜索。

0