为什么python中设置的环境变量不能持久?

2025-03-07 09:03:00
admin
原创
67
摘要:问题描述:我希望编写一个 python 脚本,通过在我将执行一些模拟代码的任何目录中运行该脚本来创建一些适当的环境变量,并且我读到我无法编写脚本来使这些环境变量在 mac os 终端中持续存在。所以有两件事:这是真的吗?和这看起来似乎是一件有用的事情;为什么一般来说这是不可能的呢?解决方案 1:您无法通过 p...

问题描述:

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

这是真的吗?

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


解决方案 1:

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

export VAR="foo"

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

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

cat .data

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

export DATA=`cat .data`

该命令获取 .data 的内容并将其放入环境变量 DATA 中。现在,如果你将其放入别名命令中,你就有了一个设置环境变量的 bash 命令:

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

您可以将该别名命令放在主目录中的 .bashrc 或 .bash_profile 文件中,以便该命令在您启动的任何新 bash shell 中可用。

解决方案 2:

一个解决方法是输出export命令,并让父 shell 对其进行评估。

thescript.py

import pipes
import random
r = random.randint(1,100)
print("export BLAHBLAH=%s" % (pipes.quote(str(r))))

..和 bash 别名(在大多数 shell 中都可以做到这一点..甚至 tcsh!):

alias setblahblahenv="eval $(python thescript.py)"

用法:

$ echo $BLAHBLAH

$ setblahblahenv
$ echo $BLAHBLAH
72

你可以输出任意的 shell 代码,包括多个命令,例如:

export BLAHBLAH=23 SECONDENVVAR='something else' && echo 'everything worked'

只要记住要小心转义任何动态创建的输出(pipes.quote模块非常适合这种情况)

解决方案 3:

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

编辑说明:所以你的问题的答案是肯定的,这是真的。但是,你可以从 shell 脚本中导出并使用点调用来获取它

在 fooexport.sh 中

export FOO="bar"

在命令提示符下

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

解决方案 4:

通常这是不可能的。为 Python 创建的新进程不能影响其父进程的环境。父进程也不能影响子进程,但父进程可以在新进程创建过程中设置子进程的环境。

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

您还可以让 python 使用所需的环境启动模拟程序。(使用envsubprocess.Popen 的参数(http://docs.python.org/library/subprocess.html))

import subprocess, os
os.chdir('/home/you/desired/directory')
subprocess.Popen(['desired_program_cmd', 'args', ...], env=dict(SOMEVAR='a_value') )

或者你可以让 python 将类似这样的 shell 脚本写入带有扩展名的文件中.sh

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

然后就chmod +x可以从任何地方运行它了。

解决方案 5:

当我遇到类似情况时,我喜欢在 shell 脚本中使用 /usr/bin/env 来“包装”我的命令行:

#!/bin/bash

/usr/bin/env NAME1="VALUE1" NAME2="VALUE2" ${*}

因此我们将此脚本命名为“myappenv”。我将其放在我的 $HOME/bin 目录中,该目录位于我的 $PATH 中。

现在我可以通过在前面添加“myappenv”来调用使用该环境的任何命令,如下所示:

myappenv dosometask -xyz

其他已发布的解决方案也有效,但这是我的个人偏好。一个优点是环境是瞬态的,因此如果我在 shell 中工作,只有我调用的命令会受到改变的环境的影响。

根据新评论修改后的版本

#!/bin/bash

/usr/bin/env G4WORKDIR=$PWD ${*}

您也可以将这一切包装在别名中。我更喜欢包装脚本方法,因为我倾向于在其中进行其他环境准备,这使我更容易维护。

解决方案 6:

正如 Benson 所回答的,但最好的解决方法是创建一个简单的 bash 函数来保存参数:

upsert-env-var (){ eval $(python upsert_env_var.py $*); }

你可以使用参数在 Python 脚本中做任何你想做的事情。要简单地添加变量,请使用以下命令:

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

解决方案 7:

正如其他人指出的那样,这不起作用的原因是环境变量存在于每个进程的内存空间中,因此当 Python 进程退出时它就会消亡。

他们指出,解决这个问题的方法是定义一个别名来做.bashrc你想做的事情,例如:

alias export_my_program="export MY_VAR=`my_program`"

但是,还有另一种(有点不靠谱的)方法,它不需要您修改.bachrc,也不需要您拥有my_program$PATH或在别名中指定它的完整路径)。这个想法是,如果程序正常调用(./my_program),则在 Python 中运行该程序,但如果程序被调用(source my_program),则在 Bash 中运行。(在脚本上使用source不会产生新进程,因此不会杀死在其中创建的环境变量。)您可以按如下方式执行此操作:

my_program.py

#!/usr/bin/env python3

_UNUSED_VAR=0
_UNUSED_VAR=0 \n<< _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!')

在 Python 中运行此程序(./my_program.py),前 3 行不会产生任何有用的效果,三重引号将注释掉 Bash 代码,从而使 Python 正常运行而不会出现任何 Bash 语法错误。

在 bash ( source my_program.py) 中获取此代码,heredoc ( << _UNUSED_VAR) 是一种用于“注释掉”第一个三重引号的 hack,否则会出现语法错误。脚本在到达第二个三重引号之前返回,从而避免出现另一个语法错误。将从正确目录(由 给出)在 Python 中export运行的结果分配给环境变量。在命令行上打印结果。my_program.py`$(dirname $0)MY_VARecho $MY_VAR`

使用示例:

$ source my_program.py
Hello environment!
$ echo $MY_VAR
Hello environment!

但是,如果正常运行,脚本仍然会执行之前执行的所有操作,除了导出环境变量:

$ ./my_program.py
Hello environment!
$ echo $MY_VAR
                                <-- Empty line

解决方案 8:

正如其他作者所指出的,当 Python 进程退出时,内存会被丢弃。但在 Python 进程期间,您可以编辑运行环境。例如:

>>> os.environ["foo"] = "bar"
>>> import subprocess
>>> subprocess.call(["printenv", "foo"])
bar
0
>>> os.environ["foo"] = "foo"
>>> subprocess.call(["printenv", "foo"])
foo
0

解决方案 9:

如果可以写入文件,另一种解决方法是使用 source 命令。让 Python 脚本将输出写入文件,该文件可以进一步用于导出变量。不过我在 Linux 上使用过这种方法。例如:

with open("vars", "w") as f:
  f.write('export foo=bar
')
  f.write('export fruit="apple"
')

然后在模拟代码中:

source vars

这些变量至少对于给定的 shell 可用。

解决方案 10:

这是一个相当古老的话题,但因为我在寻找答案的过程中发现了它——所以我将在这里添加一个额外的可能的解决方案。

如果您使用的是Windows(不是原始问题中所描述的),最简单的方法是调用setx命令,例如:

setx MY_ENV_VAR_NAME“我的价值”

您可以从python脚本调用此命令作为外部应用程序。setx有许多选项,因此您可以为当前用户、系统或特定用户设置环境变量,使用文件作为输入等。唯一的缺点是新值将在下一个命令窗口会话中首先可用(但只要您已在本地设置它 - 直到下一个会话(如果需要)您可以使用已知的值;另一种方法是 - 启动一个新的命令窗口会话)。

对于mac OS和 Windows,您还可以使用 PowerShell:

希望有帮助;-)

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   3958  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   2737  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Freshdesk、ClickUp、nTask、Hubstaff、Plutio、Productive、Targa、Bonsai、Wrike。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在项目管理过程中面临着诸多痛点,如任务分配不...
项目管理系统   74  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Monday、TeamGantt、Filestage、Chanty、Visor、Smartsheet、Productive、Quire、Planview。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多项目经理和团队在管理复杂项目时,常...
开源项目管理工具   83  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Smartsheet、GanttPRO、Backlog、Visor、ResourceGuru、Productive、Xebrio、Hive、Quire。在当今快节奏的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在选择项目管理工具时常常面临困惑:...
项目管理系统   70  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用