Popen具有冲突的可执行文件/路径

时间:2014-07-16 20:10:49

标签: python windows subprocess popen

我想使用Popen从我的Python脚本中调用ImageMagick中的“convert”实用程序,如下所示:

Popen(["convert", input_path, "-flop", output_file_path])

(上面的例子只是水平反转图像)

问题是当我在Windows中运行脚本时,它错误地调用Windows附带的convert.exe实用程序将FAT分区转换为NTFS! (位于\ Windows \ system32)

现在,如果我在system32以外的任何目录中随机打开命令提示符,并键入“convert”,它会正确运行ImageMagick可执行文件。所以,这意味着Popen会自动查看system32。如何让它不在system32中查看,并运行正确的可执行文件?

3 个答案:

答案 0 :(得分:7)

搜索程序并非易事。我明确地明确指定convert.exe可执行文件的完整路径

subprocess使用CreateProcess on Windows that looks in system32 directory even before any other directory in %PATH%

  

...如果文件名不包含扩展名,则会附加.exe。   因此,如果文件扩展名为.com,则此参数必须为   包括.com扩展名。如果文件名以句点(。)结尾   没有扩展名,或者如果文件名包含路径,则.exe不是   追加。如果文件名不包含目录路径,则   系统按以下顺序搜索可执行文件:

  1. 加载应用程序的目录。
  2. 父进程的当前目录。
  3. 32位Windows系统目录。使用GetSystemDirectory函数获取此目录的路径。
  4. 16位Windows系统目录。没有函数可以获取此目录的路径,但会搜索它。该目录的名称是System。
  5. Windows目录。使用GetWindowsDirectory函数获取此目录的路径。
  6. PATH环境变量中列出的目录。请注意,此功能不会搜索App Paths注册表项指定的每个应用程序路径。要在搜索序列中包含此每个应用程序路径,请使用ShellExecute函数。
  7. 因此convert在这种情况下相当于convert.exe。它首先查找包含sys.executable的目录,例如C:\Python27。然后在当前目录中:从哪里开始Python脚本。然后在system32中找到convert.exe(文件系统实用程序,而不是imagemagick)。

    您可以尝试从os.environ['PATH']删除system32目录,它可能(?)禁止检查它:Popen(cmd, env=no_system32_environ)但它很脆弱(比显式路径更差)。

    Python bug跟踪器存在一个相关问题:"Subprocess picks the wrong executable on Windows."


    cmd.exe(shell)使用不同的算法。见How does Windows locate files input in the shell?

    如果您设置了shell=True,那么convert程序的搜索顺序为:

    1. convert不是内部shell命令
    2. 没有明确的路径,因此搜索会继续
    3. 搜索当前目录
    4. 按列出的顺序搜索PATH环境变量指定的每个目录
    5. %PATHEXT%定义了哪些文件扩展名被检查,以及如果%PATHEXT%.com;.exe;.bat;.cmd,则转换为convert.com,convert.exe,convert.bat,convert.cmd。

答案 1 :(得分:2)

作为一种完全不同的方法,您可能需要尝试PythonMagick,这是ImageMagick的Python包装器。这样您就可以从Python中访问convert的函数,而不必生成外部进程。

答案 2 :(得分:0)

我自己也碰到了这个。在shell中运行php脚本可以访问shell $ PATH,而在Apache中运行则不会(至少不是带有Cygwin dll / exe的$ PATH)。

其次,在Windows平台上使用php中的本机Windows表示法C:/ dir / subdir / pgm,你会得到你期望的结果。

因此,多平台代码需要切换/处理路径,然后引用决策。