Xonsh "which"等效 - 如何测试(子进程模式)命令是否可用?



我想测试(从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")

最新更新