使用subprocess.call运行bash脚本时,如何访问anaconda3/bin目录中的函数



我有以下问题:我为数据分析编写了一个bash脚本,当我从终端运行它时,它运行得非常好。为了进一步自动化这个过程,我想使用一个python脚本来运行bash脚本(使用subprocess.call)、更改工作目录并重新运行脚本(等等)。当我在MacBook上这样做的时候,效果也很好。然而,我需要在Linux机器上进行分析,问题就出现在这里了。同样,从终端运行脚本运行得很好,但一旦我尝试使用python脚本执行此操作,它就无法找到用于分析的相关函数。这些函数存储在anaconda3/bin文件夹中。(Python甚至找不到像"pip"这样的其他函数)

当然,我可以在bash脚本中添加所有函数的路径,但这对我来说效率很低。所以我的问题是:有没有更好的方法告诉python在哪里查找函数?你能向我解释一下为什么从终端运行脚本有效,但当我使用subprocess.call时却无效吗?

以下是python脚本:

import subprocess
import os
path_list = ["Path1",
"Path2"
]
for path in path_list:
os.chdir(path)
subprocess.call("Users/.../bash_script", shell=True)

我只是发布我的一系列评论作为答案,因为我认为这至少对遇到类似问题的人来说是一个合理的答案(你的问题肯定很常见,可以从搜索引擎结果中进行索引)。

问题:

。。。从终端运行脚本运行得很好,但一旦我尝试使用python脚本执行此操作,它就无法找到分析的相关函数

通常,您可以使用以下工具来解决此类问题:

import subprocess
subprocess.call('echo $PATH', shell=True)

如果包含相关二进制文件/脚本等的目录。不在输出中,则您在由subprocess.call创建的shell中面临PATH问题。

OP在评论中确认的确切问题是anaconda3/bin不是您的PATH的一部分。由于安装时会将Anaconda初始化函数添加到.bashrc中,因此脚本可以在常规终端会话中工作。

答案的一部分在这里非常有用:Python-通过shell脚本激活conda-env

不过,脚本的问题在于.bashrc不是由运行shell脚本的子shell提供的(有关更多信息,请参阅此答案)。这意味着,即使您的非登录交互式shell看到conda命令,您的非交互式脚本子shell也不会看到——无论您调用conda-init多少次。

解决方案1:在脚本中手动使用Anaconda寻源功能

正如评论中提到的OP,他们的解决方法是在他们试图运行的脚本中使用添加到.bashrc中的初始化函数。尽管这可能感觉不是一个好的解决方案,但这是一个";足够好";解决方法。不幸的是,我在Linux上没有使用Anaconda,所以我没有一个确切的片段。参见下一节;"清洁剂";解决方案

解决方案2:使用bash -i运行脚本

正如上面链接的同一答案中所提到的,您可能可以使用:

bash -i Users/.../bash_script

这将告诉bash在交互模式下运行,然后在创建shell时正确地获取.bashrc文件的来源。因此,Anaconda和相关功能应该可以正常工作。

解决方案3:手动将anaconda3/bin添加到PATH

你可以看看这个答案来决定这是否是你想做的事情。请记住,他们谈论的是Windows操作系统,但大多数情况都适用于Linux。

当您将目录添加到PATH时,您特别告诉您的系统在按名称执行时始终在该目录中查找命令,例如pingwhich。如果您有冲突(例如,在/usr/bin.../anaconda3/bin中发现具有相同名称的命令),并且因此Anaconda默认情况下不会将其bin文件夹添加到您的PATH中,则这可能会产生意外行为。

这不一定是";危险的";就其本身而言,对于大多数人来说,这不是一个理想的解决方案。然而,你是自己系统的老板。如果您决定这适用于您的特定工作流,您可以将导出添加到脚本中:

export PATH="path/to/anaconda3/bin:$PATH"

这将设置PATH,以便在当前shell和子进程中使用。

解决方案4:手动sourceconda脚本(可能已过期)

如本答案中所述,您也可以选择手动获取conda.sh脚本(请记住,您的conda.sh可能在另一个目录中):

source /opt/anaconda/etc/profile.d/conda.sh

这将基本上运行该shell脚本,并将包含的功能添加到当前shell(例如subprocess.call派生的shell)。

请记住,这个答案有点老(2013年),可能不再适用,这取决于conda多年来的变化。


注释

正如我在评论中提到的,你可能想在https://unix.stackexchange.com/.您有一个有趣的配置挑战,它可能更适合于专门针对Linux的答案,因为您的问题直接来自Linux shell行为。

最新更新