为什么可以';python中设置的环境变量是否持久?

为什么可以';python中设置的环境变量是否持久?,python,persistence,environment-variables,Python,Persistence,Environment Variables,我希望编写一个python脚本,通过在我将要执行一些模拟代码的任何目录中运行该脚本来创建一些适当的环境变量,我已经读到,我无法编写一个脚本来让这些环境变量在mac os终端中持久化。所以有两件事: 这是真的吗 及 这似乎是一件有用的事情;为什么一般来说不可能呢?一般来说不可能。为python创建的新进程不能影响其父进程的环境。父进程也不能影响子进程,但父进程可以在创建新进程时设置子进程的环境 也许您可以在MacOS中的.bashrc、.profile或等效的“登录时运行”或“在每个新终端会话上运

我希望编写一个python脚本,通过在我将要执行一些模拟代码的任何目录中运行该脚本来创建一些适当的环境变量,我已经读到,我无法编写一个脚本来让这些环境变量在mac os终端中持久化。所以有两件事:

这是真的吗


这似乎是一件有用的事情;为什么一般来说不可能呢?

一般来说不可能。为python创建的新进程不能影响其父进程的环境。父进程也不能影响子进程,但父进程可以在创建新进程时设置子进程的环境

也许您可以在MacOS中的
.bashrc
.profile
或等效的“登录时运行”或“在每个新终端会话上运行”脚本中设置它们

您还可以让python使用所需的环境启动模拟程序。(将
env
参数用于subprocess.Popen())

或者,您可以让python将这样的shell脚本写入扩展名为
.sh
的文件:

export SOMEVAR=a_value
cd /home/you/desired/directory
./desired_program_cmd

然后
chmod+x
从任何地方运行它。

通常不可能。为python创建的新进程不能影响其父进程的环境。父进程也不能影响子进程,但父进程可以在创建新进程时设置子进程的环境

也许您可以在MacOS中的
.bashrc
.profile
或等效的“登录时运行”或“在每个新终端会话上运行”脚本中设置它们

您还可以让python使用所需的环境启动模拟程序。(将
env
参数用于subprocess.Popen())

或者,您可以让python将这样的shell脚本写入扩展名为
.sh
的文件:

export SOMEVAR=a_value
cd /home/you/desired/directory
./desired_program_cmd

然后
chmod+x
在任何地方运行它。

如果在python脚本(或任何其他脚本或程序)中设置环境变量,则不会影响父shell

编辑澄清: 所以你的问题的答案是肯定的,这是真的。 但是,您可以从shell脚本中导出,并使用点调用为其提供源代码

在foodexport.sh中

export FOO="bar"
在命令提示下

$ . ./fooexport.sh
$ echo $FOO
bar

如果在python脚本(或任何其他脚本或程序)中设置环境变量,则不会影响父shell

编辑澄清: 所以你的问题的答案是肯定的,这是真的。 但是,您可以从shell脚本中导出,并使用点调用为其提供源代码

在foodexport.sh中

export FOO="bar"
在命令提示下

$ . ./fooexport.sh
$ echo $FOO
bar

您不能从python中执行此操作,但是一些聪明的bash技巧可以执行类似的操作。基本推理是:环境变量存在于每个进程的内存空间中。使用fork()创建新进程时,它将继承其父进程的环境变量。当您在shell(例如bash)中设置环境变量时,如下所示:

export VAR="foo"
您要做的是告诉bash将其进程空间中的变量VAR设置为“foo”。运行程序时,bash使用fork()然后使用exec()来运行程序,因此从bash运行的任何东西都会继承bash环境变量

现在,假设您想要创建一个bash命令,该命令使用当前目录中名为“.DATA”的文件中的内容设置一些环境变量数据。首先,您需要使用命令从文件中获取数据:

cat .data
这会打印数据。现在,我们要创建一个bash命令来设置环境变量中的数据:

export DATA=`cat .data`
该命令获取.data的内容并将其放入环境变量data中。现在,如果将其放在alias命令中,则有一个bash命令用于设置环境变量:

alias set-data="export DATA=`cat .data`"

您可以将alias命令放在主目录中的.bashrc或.bash_配置文件中,以便在启动的任何新bash shell中都可以使用该命令

您不能从python中执行此操作,但是一些聪明的bash技巧可以执行类似的操作。基本推理是:环境变量存在于每个进程的内存空间中。使用fork()创建新进程时,它将继承其父进程的环境变量。当您在shell(例如bash)中设置环境变量时,如下所示:

export VAR="foo"
您要做的是告诉bash将其进程空间中的变量VAR设置为“foo”。运行程序时,bash使用fork()然后使用exec()来运行程序,因此从bash运行的任何东西都会继承bash环境变量

现在,假设您想要创建一个bash命令,该命令使用当前目录中名为“.DATA”的文件中的内容设置一些环境变量数据。首先,您需要使用命令从文件中获取数据:

cat .data
这会打印数据。现在,我们要创建一个bash命令来设置环境变量中的数据:

export DATA=`cat .data`
该命令获取.data的内容并将其放入环境变量data中。现在,如果将其放在alias命令中,则有一个bash命令用于设置环境变量:

alias set-data="export DATA=`cat .data`"

您可以将alias命令放在主目录中的.bashrc或.bash_配置文件中,以便在启动的任何新bash shell中都可以使用该命令

我喜欢在shell脚本中使用/usr/bin/env来“包装”我的命令行,当我发现自己处于类似情况时:

#!/bin/bash

/usr/bin/env NAME1="VALUE1" NAME2="VALUE2" ${*}
让我们把这个脚本称为“myappenv”。我把它放在我的$HOME/bin目录中,该目录位于我的$PATH中

现在,我可以使用该环境调用任何命令,只需在“myappenv”前面加上如下前缀:

其他发布的解决方案也可以,但这是我个人的偏好。一个优点是环境是暂时的,因此如果我在shell中工作,那么只有我调用的命令会受到更改的环境的影响

根据新评论修改版本

#!/bin/bash

/usr/bin/env G4WORKDIR=$PWD ${*}
你也可以用一个别名来概括这一切。我更喜欢包装器脚本ap
var = sys.argv[1]
val = sys.argv[2]
if os.environ.get(var, None):
    print "export %s=%s:%s" % (var, val, os.environ[var])
else:
    print "export %s=%s" % (var, val)
upsert-env-var VAR VAL
alias export_my_program="export MY_VAR=`my_program`"
#!/usr/bin/env python3

_UNUSED_VAR=0
_UNUSED_VAR=0 \
<< _UNUSED_VAR
#=======================
# Bash code starts here
#=======================
'''
_UNUSED_VAR
export MY_VAR=`$(dirname $0)/my_program.py`
echo $MY_VAR
return
'''

#=========================
# Python code starts here
#=========================
print('Hello environment!')
$ source my_program.py
Hello environment!
$ echo $MY_VAR
Hello environment!
$ ./my_program.py
Hello environment!
$ echo $MY_VAR
                                <-- Empty line
>>> os.environ["foo"] = "bar"
>>> import subprocess
>>> subprocess.call(["printenv", "foo"])
bar
0
>>> os.environ["foo"] = "foo"
>>> subprocess.call(["printenv", "foo"])
foo
0