我想测试(从xonsh(命令是否可用。如果我在xonsh命令提示符下尝试:
which bash
然后它就工作了:
user@server ~ $ which bash
/usr/bin/bash
但它不适用于xonsh脚本:
#!/usr/bin/env xonsh
$RAISE_SUBPROC_ERROR = True
try:
which bash
print("bash is available")
except:
print("bash is not available")
因为它导致了这个错误:
NameError: name 'which' is not defined
我知道which
是一个内置的shell。例如,它不是一个可执行文件。但它可以在xnosh命令提示符下使用。那么,为什么它在xonsh脚本中不可用呢?最终的问题是:如何(从xonsh脚本(测试(子流程模式(命令是否可用?
import shutil
print(shutil.which('bash'))
虽然nagylzs的回答让我找到了正确的解决方案,但我发现它不够。
shutil.which
默认为os.environ['PATH']
。在我的机器上,默认的os.environ['PATH']
不包含xonsh识别的活动PATH。
~ $ os.environ['PATH']
'/usr/bin:/bin:/usr/sbin:/sbin'
我发现我需要通过$PATH
来可靠地解决xonsh环境中的"which"。
~ $ $PATH[:2]
['/opt/google-cloud-sdk/bin', '/Users/jaraco/.local/bin']
~ $ import shutil
~ $ shutil.which('brew', path=os.pathsep.join($PATH))
'/opt/homebrew/bin/brew'
最新版本的xonsh
包含一个内置的which
命令。不幸的是,如果找不到目标,包含的版本将在stdout上发出错误,这种行为不适合非交互式使用。
正如另一个答案中所提到的,which
存在于当前版本的xonsh中(截至2022年12月15日为0.13.4(,因此您的脚本可以工作。然而,它会输出自己的错误消息,因此有必要重定向stderr
以清除它
此外,除非您也重定向其stdout
(使用all>
(,否则捕获其输出可能是一个好主意,因此最终版本将如下所示:
#!/usr/bin/env xonsh
$RAISE_SUBPROC_ERROR = True
try:
bash = $(which bash err> /dev/null)
print(f"bash is available: {bash}")
except:
print("bash is not available")