本问题已经有最佳答案,请猛点这里访问。
在python中启动项目时,我想将一些环境变量保存在名为environment_variables的文件中,并在bashrc中源代码这个文件。
文件如下所示:
13username=$(whoami)
# project root path
export PROJECT_DIR='/home/'$username'/nuclei_segmentation/'
# project data path
export DATA_DIR=$PROJECT_DIR"data/"
# location of models
export MODEL_DIR=$PROJECT_DIR"models/"
# project output data
export OUTPUT_DIR=$PROJECT_DIR"output/"
我想更改PROJECT_DIR路径,使其与平台/名称无关。所以这个environment_variables文件将始终在项目的根目录中,我想将PROJECT_DIR设置为始终是environment_variables文件的位置。
我以为我可以用PWD来完成这个任务,但是当从bashrc调用时,这会产生一个错误,我还想到了一个使用find从根目录中搜索文件的解决方案,但是这看起来很复杂,并且认为必须有更好的方法?
这听起来很像xy问题。你为什么要做这些事情?您的方法可能不是解决您试图解决的潜在问题的好方法。
也许你是对的!也许我项目的X部分是,在Python数据科学项目中设置环境变量的一个好方法是什么,它是可复制的,并且与平台无关?
老实说,当我第一次将文件复制到项目目录以硬编码PROJECT_DIR的值时,我只需要编辑该文件。
是的,可以,但我想一定有一个很好的解决办法
"平台/名称独立"是什么意思?这是可以移植到POSIX平台,还是也可以移植到Windows?究竟什么情况下$PWD不起作用,你会得到什么错误?
@三倍我的意思是,如果我把这个项目给其他人,他们把它放在一个不同的位置(即他们的路径不同),变量仍然会被创建。所以对我来说是在以东十一〔2〕号,但他们的可能是以东十一〔3〕号。我想找一个不需要硬编码位置的方法。
如果我使用$PWD,那么我得到.bashrc文件的位置,例如我的主目录,而不是到environment_variables文件的路径。
@威廉姆格里姆斯,如果你想找到一个源文件的路径,这就是$BASH_SOURCE的目的。我们有很多以前存在的问题,包括从内部获取bash脚本的源目录。另请参见bashfaq 28。
@查理斯达菲,我不认为这是一个复制品,类似的答案是投了低票,显然根本不是OP想要的。
@tripleee,…如果您想编辑这个问题,使它不再主要是关于bash的标题,而是明确地询问关于帮助Python程序找到其安装位置(或其他)的最佳实践的问题,我同意它不再是重复的。也就是说,我重读了这个问题,但仍然看不到操作是如何"明确拒绝"$BASH_SOURCE--它们是明确拒绝$PWD,这是正确的,因为如果您想要源文件的位置,shell当前的工作目录将不会给出正确的结果。
@尽管如此,标题中的问题是重复的,如果他们想做的是设置环境变量相对于登录时从他们的点文件(与该标题的纯语言一致的正文文本的读取)中获得的environment_variables文件的位置,那么这显然也是重复的。
@查理斯达菲也不确定我是否完全理解手术的意图,也不确定是否值得这么做。不过,你能链接到你提到的另一个副本吗?
@tripleee,我不是指当前链接的副本以外的任何副本;是的,它接受的答案是调用pwd,但它在cd"$(dirname"${BASH_SOURCE[0]}")"之后的子shell中这样做,使得输出与op指示$PWD对它们不起作用的情况不同。
@Triplee和@CharlesDuffy非常感谢你们的投入。最后,我使用了NUC_SEG_DIR="$( cd"$( dirname"${BASH_SOURCE[0]}" )" && pwd )",正如environment_variables中建议的那样,这是一种治疗方法。然后在python中,我创建与之相关的变量。我很抱歉以一种有点复杂的方式提问,但我想我也希望在@tripleee友好提供的最佳实践方面有更大的背景。多谢
如果我完全理解你想去哪里,我的建议是
使代码尽可能地脱离当前目录。
如果可以避免的话,不要在用户环境中乱丢多个变量。
如果你必须有环境变量,给它们一个名称,清楚地传达它们与什么相关。
在一些更具体的例子中,命名项目根目录的单个变量应该是您真正需要的。如果预期的文件在当前目录中,则不需要设置它。
1export NUC_SEG_DIR=$HOME/nuclei_segmentation
在python代码中,输入合理的默认值。在这种特殊情况下,希望os.path.join(os.environ['NUC_SEG_DIR'], 'data')指向您的data目录等。如果用户想覆盖它,使用符号链接就足够容易了。确保这在代码中是参数化的,这样如果您希望在将来配置它,可以在一个地方轻松重写。可能有点像
4def nuc_seg(root_dir=os.environ['NUC_SEG_DIR'], data_dir='./data', model_dir='./models', output_dir='./output'):
if root_dir == '':
root_dir='.'
... your code here
也许稍后,让您的命令行界面允许用户通过命令行选项或配置文件来重写这些值。
同样,不需要用户编辑他们的.bash_profile或类似的东西——如果他们想在不同的目录中运行多个实验,或者其他什么?他们可以弄清楚如何使环境变量成为永久变量,或者,如果您的用户不希望熟悉shell的基础知识,您甚至可以将其作为一个选项记录下来。
在脚本文件中使用dirname $0查找当前脚本文件所在的目录
例如export PROJECT_DIR=$(dirname $0)。
不完全确定语法?
使用引号来处理不规则的文件名;PROJECT_DIR="$(dirname"$0")"…不确定export是否真的是必要的;许多初学者不必要地将其用于不将导出到子流程的变量。
谢谢@triplee,我刚试过,得到以下错误:dirname: invalid option -- 'b'。
那么你的$0是-bash(或-sh),这意味着你正在寻找脚本。这个答案是关于找到当前运行脚本的源代码的,但是如果您没有运行脚本,那么这当然是没有意义的。
哦,不好意思弄混了,是的,我正在巴什尔克寻找脚本。我可以把environment_variables制作成bash脚本,然后运行它吗,如果我只输入#!/usr/bin/env bash