简体   繁体   English

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

[英]How can I access functions inside the anaconda3/bin directory when running a bash script with subprocess.call?

I have the following problem: I wrote a bash script for data analysis that works perfectly fine when I run it from the terminal.我有以下问题:我编写了一个用于数据分析的 bash 脚本,当我从终端运行它时效果很好。 To further automate the process I wanted to use a python script that runs the bash script (using subprocess.call), changes the working directory, and reruns the script (and so on).为了进一步自动化该过程,我想使用运行 bash 脚本(使用 subprocess.call)、更改工作目录并重新运行脚本(等等)的 python 脚本。 This also worked fine when I did it on my MacBook.当我在 MacBook 上执行此操作时,这也可以正常工作。 However, I need to do the analysis on a Linux machine and here the problem occurred.但是,我需要在 Linux 机器上进行分析,问题就出现在这里。 Again, running the script from the terminal worked fine but once I tried doing this with my python script it fails to find the relevant functions for the analysis.同样,从终端运行脚本运行良好,但是一旦我尝试使用我的 python 脚本执行此操作,它就无法找到用于分析的相关函数。 The functions are stored inside the anaconda3/bin folder.这些函数存储在 anaconda3/bin 文件夹中。 (Python does not even find other functions like "pip") (Python 甚至找不到像“pip”这样的其他函数)

Of course, I could add the path to all the functions in the bash script but this seems very inefficient to me.当然,我可以在 bash 脚本中添加所有函数的路径,但这对我来说似乎效率很低。 So my question is: is there any better way of telling python where to look for the functions?所以我的问题是:有没有更好的方法告诉 python 在哪里寻找功能? And can you maybe explain to me why running the script from the terminal works but not when I use subprocess.call?您能否向我解释为什么从终端运行脚本有效,但在我使用 subprocess.call 时无效?

Here is the python script:这是 python 脚本:

import subprocess
import os

path_list = ["Path1",
             "Path2"
             ]

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

I'm just posting my series of comments as an answer since I think this at least constitutes a reasonable answer for anyone running into a similar issue (your question could definitely be common enough to index from search engine results).我只是发布我的一系列评论作为答案,因为我认为对于遇到类似问题的任何人来说,这至少构成了一个合理的答案(您的问题肯定足够普遍,可以从搜索引擎结果中索引)。

Issue:问题:

...running the script from the terminal worked fine but once I tried doing this with my python script it fails to find the relevant functions for the analysis ...从终端运行脚本运行良好,但是一旦我尝试使用我的 python 脚本执行此操作,它就无法找到相关的分析函数

In general, you can troubleshoot this kind of problem with:通常,您可以通过以下方式解决此类问题:

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

If the directory that contains the relevant binaries/scripts/etc.如果包含相关二进制文件/脚本/等的目录。 is not in the output, then you are facing a PATH issue in the shell created by subprocess.call .不在 output 中,那么您在 subprocess.call 创建的subprocess.call中面临PATH问题。

The exact problem as confirmed by the OP in comments is that anaconda3/bin is not part of your PATH . OP 在评论中确认的确切问题是anaconda3/bin不是您的PATH的一部分。 Your script works in a regular terminal session because of the Anaconda initialization function that gets added to your .bashrc when installing.您的脚本在常规终端 session 中工作,因为 Anaconda 初始化 function 会在安装时添加到您的.bashrc中。

Part of an answer that is very helpful here: Python - Activate conda env through shell script部分答案在这里非常有用: Python - 通过 shell 脚本激活 conda env

The problem with your script, though, lies in the fact that the.bashrc is not sourced by the subshell that runs shell scripts (see this answer for more info).但是,您的脚本的问题在于 .bashrc 不是由运行 shell 脚本的子shell 提供的(有关更多信息,请参见此答案)。 This means that even though your non-login interactive shell sees the conda commands, your non-interactive script subshells won't - no matter how many times you call conda init.这意味着即使您的非登录交互式 shell 看到 conda 命令,您的非交互式脚本子外壳也不会 - 无论您调用 conda init 多少次。

Solution 1: Manually use the Anaconda sourcing function in your script解决方案 1:在脚本中手动使用 Anaconda 采购 function

As the OP mentioned in the comments, their workaround was to use the initialization function added to their .bashrc in the script they are trying to run.正如评论中提到的OP,他们的解决方法是使用初始化 function 在他们试图运行的脚本中添加到他们的.bashrc中。 Although this perhaps feels like not a great solution, this is a "good enough" workaround.尽管这可能感觉不是一个很好的解决方案,但这是一个“足够好”的解决方法。 Unfortunately I don't use Anaconda on Linux so I don't have an exact snippet of what this looks like.不幸的是,我没有在 Linux 上使用 Anaconda,所以我没有确切的片段。 See the next section for a possibly "cleaner" solution.有关可能的“更清洁”解决方案,请参阅下一节。

Solution 2: Use bash -i to run your script解决方案 2:使用bash -i运行您的脚本

As mentioned in the same answer linked above, you might be able to use:如上面链接的相同答案中所述,您可能可以使用:

bash -i Users/.../bash_script

This will tell bash to run in interactive mode, which then properly sources your .bashrc file when creating the shell.这将告诉bash在交互模式下运行,然后在创建 shell 时正确地获取您的.bashrc文件。 As a result, Anaconda and related functions should work properly.因此,Anaconda 和相关功能应该可以正常工作。

Solution 3: Manually add anaconda3/bin to PATH解决方案3:手动添加anaconda3/binPATH

You can check out this answer to decide if this is something you want to do.您可以查看此答案以确定这是否是您想要做的事情。 Keep in mind they are speaking about a Windows OS but most of the same applies to Linux.请记住,他们谈论的是 Windows 操作系统,但大多数情况同样适用于 Linux。

When you add the directory to your PATH , you are specifically telling your system to always look in that directory for commands when executing by name, eg ping or which .当您将目录添加到您的PATH时,您明确告诉您的系统在按名称执行时始终在该目录中查找命令,例如pingwhich This can have unexpected behavior if you have conflicts (eg a command is found with the same name in /usr/bin and .../anaconda3/bin ), and as such Anaconda does not add its bin folder to your PATH by default.如果您有冲突(例如在/usr/bin.../anaconda3/bin中找到具有相同名称的命令),这可能会出现意外行为,因此 Anaconda 默认情况下不会将其bin文件夹添加到您的PATH中。

This is not necessarily "dangerous" per se, it's just not an ideal solution for most people.这本身不一定是“危险的”,对于大多数人来说,这不是一个理想的解决方案。 However, you are the boss of your own system.但是,您是自己系统的老板。 If you decide this works for your particular workflow, you can just add the export to your script:如果您决定这适用于您的特定工作流程,您只需将导出添加到您的脚本中:

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

This will set the PATH for use in the current shell and sub-processes.这将设置用于当前 shell 和子进程的PATH

Solution 4: Manually source the conda script (possibly outdated)解决方案 4:手动conda source (可能已过时)

As mentioned in this answer , you can also opt to manually source the conda.sh script (keep in mind your conda.sh might be in another directory):this answer中所述,您还可以选择手动获取conda.sh脚本(请记住您的conda.sh可能位于另一个目录中):

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

This will essentially run that shell script and add the included functionality to the current shell (eg the one spawned by subprocess.call ).这将基本上运行 shell 脚本并将包含的功能添加到当前 shell (例如由subprocess.call产生的功能)。

Keep in mind this answer is quite a bit older (~2013) and may not apply anymore, depending how much conda has changed over the years.请记住,这个答案有点老(~2013),可能不再适用,这取决于conda多年来发生了多少变化。


Notes笔记

As I mentioned in the comments, you may want to post some related questions on https://unix.stackexchange.com/ .正如我在评论中提到的,您可能想在https://unix.stackexchange.com/上发布一些相关问题。 You have an interesting configuration challenge that may be better suited for answers specifically pertaining to Linux, since your issue is sourcing directly from Linux shell behavior.您有一个有趣的配置挑战,可能更适合与 Linux 相关的答案,因为您的问题直接来自 Linux shell 行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 当我使用 subprocess.call() 切换用户时,如何保持程序运行? - How can I keep my program running when I use subprocess.call() to switch user? 在没有外壳的情况下使用subprocess.call时如何将字符串传递给脚本 - How can I pipe a string to a script when using subprocess.call without a shell 我如何在python中从subprocess.call调用多个文件(bash文件) - how can i call mutiple files(bash files) from subprocess.call in python 用Subprocess.call()在脚本内部输入 - input inside script with Subprocess.call() 使用subprocess.call()运行bin / buildout失败 - Running bin/buildout using subprocess.call() fails 使用subprocess.call()运行程序时,如何获取程序创建的日志文件? - How do I get the log file a program creates when running it with subprocess.call()? / usr / bin / python:使用subprocess.call时在'/'中找不到'__main__.py' - /usr/bin/python: can't find '__main__.py' in '/' when using subprocess.call 为什么无法“ cd”到subprocess.call中的文件夹? - How come I can't “cd” to a folder in subprocess.call? 何时使用subprocess.call()或subprocess.Popen(),运行airodump - When to use subprocess.call() or subprocess.Popen(), running airodump 调用 subprocess.call(['.', bash_path]) 时权限被拒绝 - Permission denied when calling subprocess.call(['.', bash_path])
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM