Macos 查找可执行文件时bash的奇怪行为

Macos 查找可执行文件时bash的奇怪行为,macos,bash,python-3.x,osx-mavericks,Macos,Bash,Python 3.x,Osx Mavericks,我正在开发一个Python应用程序,该应用程序在内部必须调用ninja命令,但它找不到带有子流程模块的可执行文件。当我传递shell=True时,它确实会找到可执行文件,但不会向进程传递参数。使用os.system()工作正常 subprocess.call(['ninja'] + args) # Can't find ninja subprocess.call(['ninja'] + args, shell=True) # Finds & runs ninj

我正在开发一个Python应用程序,该应用程序在内部必须调用
ninja
命令,但它找不到带有
子流程
模块的可执行文件。当我传递
shell=True
时,它确实会找到可执行文件,但不会向进程传递参数。使用
os.system()
工作正常

subprocess.call(['ninja'] + args)              # Can't find ninja
subprocess.call(['ninja'] + args, shell=True)  # Finds & runs ninja, but the additional arguments int "args" are not passed
os.system(' '.join(shlex.quote(x) for x in ['ninja'] + args))  # Works fine
当我检查
ninja
bash
中的位置时,我开始觉得奇怪

$ which ninja
$ type ninja
ninja is hashed (/Users/niklas/Bin/ninja)
$ echo $PATH
~/Bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/texbin:/Library/Frameworks/Python.framework/Versions/3.4/bin/:/Users/niklas/Documents/apache-maven-3.3.3/bin:/Users/niklas/Documents/grib2json-0.8.0-SNAPSHOT/bin
  • 哪个
    找不到
    忍者
  • 输入忍者
    它位于
    /Users/niklas/Bin/ninja
  • 路径
    /Users/niklas/Bin
    不在
    $path

  • 我这里的设置出了什么问题?为什么bash实际上可以找到
    ninja
    ,而Python只能在
    shell=True
    模式下找到,那么为什么没有传递附加参数呢?

    如果设置
    shell=True
    ,那么命令必须是字符串而不是列表。考虑:

    >>> import subprocess
    >>> subprocess.call(['echo', 'hello'], shell=True)
    
    0
    >>> subprocess.call('echo hello', shell=True)
    hello
    0
    
    如果传递的列表为
    shell=True
    ,则只考虑列表的第一项:

    >>> subprocess.call(['echo hello', 'hello'], shell=True)
    hello
    0
    >>> 
    
    路径/Users/niklas/Bin不在$path中

    是的。这是第一项:

    $ echo $PATH
    ~/Bin:/usr/local/bin:...
    

    …假设您是
    niklas

    如果您正在设置
    shell=True
    ,则您的命令必须是字符串而不是列表。考虑:

    >>> import subprocess
    >>> subprocess.call(['echo', 'hello'], shell=True)
    
    0
    >>> subprocess.call('echo hello', shell=True)
    hello
    0
    
    如果传递的列表为
    shell=True
    ,则只考虑列表的第一项:

    >>> subprocess.call(['echo hello', 'hello'], shell=True)
    hello
    0
    >>> 
    
    路径/Users/niklas/Bin不在$path中

    是的。这是第一项:

    $ echo $PATH
    ~/Bin:/usr/local/bin:...
    

    …假设您是
    niklas

    问题在于
    ~
    是一种bashism,而python调用os.execvp()来执行subprocess.call(),这显然是在使用execvp(),系统调用,不进行波浪展开

    您的路径应为
    /Users/niklas/Bin:…
    。当您设置
    PATH=~/Bin:$PATH
    时,平铺扩展通常由shell完成

    所以bash可以找到它,因为它每次都会重新进行tilde扩展,但是execvp()永远找不到它


    正如@larsks所说,
    shell=True
    需要一个字符串。

    问题是
    ~
    是一种bash主义,而python调用os.execvp()来完成子进程.call(),这显然是使用execvp(),系统调用,不进行tide扩展

    您的路径应为
    /Users/niklas/Bin:…
    。当您设置
    PATH=~/Bin:$PATH
    时,平铺扩展通常由shell完成

    所以bash可以找到它,因为它每次都会重新进行tilde扩展,但是execvp()永远找不到它


    正如@larsks所说,
    shell=True
    需要一个字符串。

    您可能有hash-p。。。忍者在你的.bashrc或一些类似的禁止配置文件中,你可能有散列-p。。。忍者在你的.bashrc或者类似的bans档案文件中