如何在Python中设置环境变量


658

我需要在python脚本中设置一些环境变量,并且我希望从python调用的所有其他脚本来查看设置的环境变量。

如果我做

os.environ["DEBUSSY"] = 1`

它抱怨说1必须是字符串。

我还想知道一旦设置好如何在python(在脚本的后半部分)中读取环境变量。




与问题无关:我读了var。名字叫
艾哈迈德

Answers:


790

环境变量必须是字符串,因此请使用

os.environ["DEBUSSY"] = "1"

将变量DEBUSSY设置为字符串1

以后要访问此变量,只需使用:

print(os.environ["DEBUSSY"])

子进程会自动继承父进程的环境变量-无需您执行任何特殊操作。


20
在某些平台上,修改os.environ实际上不会修改当前进程或子进程的系统环境。有关更多信息,请参阅文档:docs.python.org/2/library/os.html#os.environ
Evan

8
@Evan可能有一些不支持的Unix历史版本putenv(),但是对于那些Unixen,您无能为力。我使用过的AIX和HPUX的旧版本也支持它。如果任何人今天实际上都能找到不支持它的计算机,我会严重怀疑他们是否能够在该计算机上运行Python。:)
Sven Marnach '16

3
注意:引用@Evan的上述参考,对环境的此类更改会影响以os.system(),popen()或fork()和execv()开头的子进程。 换句话说,请记住,这种方法不会修改程序的运行方式,只会修改程序的子级运行方式。没错,您的程序可以设置和读取环境变量,但只能从其为其子级配置的环境中进行。另请参阅:更改当前的流程环境。到目前为止,我还没有找到Python脚本修改其父环境的方法。
CODE-READ

1
@SvenMarnach是自动的声明“子进程继承父进程真正的像bash shell的环境。
克里希纳皇座

@darth_coder对于类似Unix的操作系统上的所有进程都是如此。我不了解其他操作系统。请注意,除非导出壳变量,否则它们不会存储在环境中。
Sven Marnach '17

114

您可能需要考虑其他方面的代码健壮性;

当您将整数值的变量存储为环境变量时,请尝试

os.environ['DEBUSSY'] = str(myintvariable)

然后为了进行检索,请考虑为避免错误,应尝试

os.environ.get('DEBUSSY', 'Not Set')

可能用“ -1”代替“未设置”

所以,把所有这些放在一起

myintvariable = 1
os.environ['DEBUSSY'] = str(myintvariable)
strauss = int(os.environ.get('STRAUSS', '-1'))
# NB KeyError <=> strauss = os.environ['STRAUSS']
debussy = int(os.environ.get('DEBUSSY', '-1'))

print "%s %u, %s %u" % ('Strauss', strauss, 'Debussy', debussy)

3
您能告诉我如何在Linux机器上设置变量,所有平台的代码是否相同?
Anurag-Sharma 2014年

2
对于缺少的整数,将-1存储很少。更好的选择是myvar = int(os.environ.get('MYVAR')) if os.environ.get('MYVAR', '') != '' else None–如果没有提供任何数字,那就将是None
本杰明·阿特金

1
如果要处理整数,则-1是有意义的。尽管我可能会将变量/常量设置为我将用于未设置的值(例如value_not_set = '-1')。然后,您可以使用debussy = int(os.environ.get('DEBUSSY', value_not_set))
yeOldeDataSmythe

68

os.environ行为类似于python字典,因此可以执行所有常见的字典操作。除了其他答案中提到的getset操作之外,我们还可以简单地检查键是否存在。键和值应存储为字符串

Python 3

对于python 3,字典使用in关键字而不是has_key

>>> import os
>>> 'HOME' in os.environ  # Check an existing env. variable
True
...

Python 2

>>> import os
>>> os.environ.has_key('HOME')  # Check an existing env. variable
True
>>> os.environ.has_key('FOO')   # Check for a non existing variable
False
>>> os.environ['FOO'] = '1'     # Set a new env. variable (String value)
>>> os.environ.has_key('FOO')
True
>>> os.environ.get('FOO')       # Retrieve the value
'1'

使用时要注意一件事os.environ

尽管子进程从父进程继承了环境,但是我最近遇到了一个问题,并弄清楚了,如果在运行python脚本时还有其他脚本在更新环境,那么os.environ再次调用将不会反映最新的值

文档摘录:

首次导入os模块时(通常是在Python启动期间作为处理site.py的一部分)捕获了此映射。此时间之后对环境所做的更改不会反映在os.environ中,除非直接修改os.environ进行更改。

os.environ.data 存储所有环境变量的是一个dict对象,其中包含所有环境值:

>>> type(os.environ.data)  # changed to _data since v3.2 (refer comment below)
<type 'dict'>

1
创建流程时设置流程的环境变量。此后所做的任何更改都不会影响进程自己的环境变量副本。这是所有进程通用的,而不仅仅是Python。此外,os.environ.data在Python 3.2中被重命名为os.environ._data,下划线前缀表明您不应该直接阅读它。无论如何,无论如何os.environ._data都不会有更新的值。
艾维格

是的,我现在明白了。我想与其他来访者分享我最初的惊喜。感谢您指出自3.2以来对变量名称的更新,将更新答案。
sisanared '18年

21

如果我做os.environ [“ DEBUSSY”] = 1,它会抱怨说1必须是字符串。

然后做

os.environ["DEBUSSY"] = "1"

我也想知道一旦我设置了如何在python(在脚本的后半部分)中读取环境变量。

只需使用os.environ["DEBUSSY"],如

some_value = os.environ["DEBUSSY"]

19

设置变量:

使用键的项目分配方法:

import os    
os.environ['DEBUSSY'] = '1'  #Environ Variable must be string not Int

获取或检查其是否存在,

由于os.environ是一个实例,您可以尝试对象方式。

方法1:

os.environ.get('DEBUSSY') # this is error free method if not will return None by default

将获得'1'作为返回值

方法2:

os.environ['DEBUSSY'] # will throw an key error if not found!

方法3:

'DEBUSSY' in os.environ  # will return Boolean True/False

方法4:

os.environ.has_key('DEBUSSY') #last 2 methods are Boolean Return so can use for conditional statements

16

您应该将字符串值分配给环境变量。

os.environ["DEBUSSY"] = "1"

如果要读取或打印环境变量,请使用

print os.environ["DEBUSSY"]

此更改仅对分配了当前过程的当前过程有效,不会永久更改该值。子进程将自动继承父进程的环境。

在此处输入图片说明


5
“此更改仅对分配它的当前过程有效,它不会永久更改值。”这回答了我有关设置环境变量的范围的问题。
spitfiredd

2
如果我退出python shell,先前设置的os environmet消失了。
MeadowMuffins

如何在Windows中设置环境变量?我试过了,set [<name>=[<value>]]但仅适用于当前正在运行的进程。当我关闭cmd时,它不存在,即使打开,其他程序也看不到它。
Filip


14

我一直在尝试添加环境变量。我的目标是将一些用户信息存储到系统变量中,以便可以将这些变量用于将来的解决方案,以替代配置文件。但是,下面的代码中描述的方法完全没有帮助。

import os
os.environ["variable_1"] = "value_1"
os.environ["variable_2"] = "value_2"
# To Verify above code
os.environ.get("variable_1")
os.environ.get("variable_2")

这个简单的代码块运行良好,但是,这些变量存在于各自的进程中,因此您将无法在Windows系统设置的环境变量选项卡中找到它们。上面的代码几乎没有达到我的目的。这里讨论这个问题:变量保存问题

os.environ.putenv(key, value)

另一个失败的尝试。因此,最后,我通过模仿包装在os包系统类中的Windows shell命令,成功地将变量保存在窗口环境寄存器中。以下代码描述了此成功尝试。

os.system("SETX {0} {1} /M".format(key, value))

希望对您中的某些人有所帮助。


12

应该注意的是,如果您尝试将环境变量设置为bash评估,它将不会存储您期望的结果。例:

from os import environ

environ["JAVA_HOME"] = "$(/usr/libexec/java_home)"

这不会像在shell中那样对它求值,因此/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home您将获得原义表达式,而不是获取路径$(/usr/libexec/java_home)

确保在设置环境变量之前对其进行评估,如下所示:

from os import environ
from subprocess import Popen, PIPE

bash_variable = "$(/usr/libexec/java_home)"
capture = Popen(f"echo {bash_variable}", stdout=PIPE, shell=True)
std_out, std_err = capture.communicate()
return_code = capture.returncode

if return_code == 0:
    evaluated_env = std_out.decode().strip()
    environ["JAVA_HOME"] = evaluated_env
else:
    print(f"Error: Unable to find environment variable {bash_variable}")

11

您可以使用os.environ字典来访问环境变量。

现在,我遇到的一个问题是,如果我试图用来os.system运行设置环境变量的批处理文件(在**。bat *文件中使用SET命令),那么它实际上不会为您的python环境设置它们(但对于使用该os.system函数创建的子进程)。为了实际获取在python环境中设置的变量,我使用以下脚本:

import re
import system
import os

def setEnvBat(batFilePath, verbose = False):
    SetEnvPattern = re.compile("set (\w+)(?:=)(.*)$", re.MULTILINE)
    SetEnvFile = open(batFilePath, "r")
    SetEnvText = SetEnvFile.read()
    SetEnvMatchList = re.findall(SetEnvPattern, SetEnvText)

    for SetEnvMatch in SetEnvMatchList:
        VarName=SetEnvMatch[0]
        VarValue=SetEnvMatch[1]
        if verbose:
            print "%s=%s"%(VarName,VarValue)
        os.environ[VarName]=VarValue

9

当您使用环境变量(添加/修改/删除变量)时,一个好的做法是在函数完成时恢复以前的状态。

您可能需要类似modified_environ上下文管理器的问题来还原环境变量。

经典用法:

with modified_environ(DEBUSSY="1"):
    call_my_function()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.