【发布时间】:2011-08-23 16:48:19
【问题描述】:
我需要在 Python 脚本中设置一些环境变量,并且我希望从 Python 调用的所有其他脚本都能看到环境变量的设置。
如果我这样做,
os.environ["DEBUSSY"] = 1
它抱怨说1 必须是一个字符串。
我也想知道一旦我设置了它,如何在 Python 中读取环境变量(在脚本的后半部分)。
【问题讨论】:
标签: python environment-variables
我需要在 Python 脚本中设置一些环境变量,并且我希望从 Python 调用的所有其他脚本都能看到环境变量的设置。
如果我这样做,
os.environ["DEBUSSY"] = 1
它抱怨说1 必须是一个字符串。
我也想知道一旦我设置了它,如何在 Python 中读取环境变量(在脚本的后半部分)。
【问题讨论】:
标签: python environment-variables
环境变量必须是字符串,所以使用
os.environ["DEBUSSY"] = "1"
将变量DEBUSSY设置为字符串1。
以后要访问这个变量,只需使用:
print(os.environ["DEBUSSY"])
子进程自动继承父进程的环境变量 -- 无需您进行任何特殊操作。
【讨论】:
putenv(),但对于那些 Unixen,无论如何你都无能为力。甚至我使用的旧版本的 AIX 和 HPUX 也支持它。如果今天真的有人能够找到不支持它的计算机,我非常怀疑他们是否能够在那台计算机上运行 Python。 :)
import os,否则这将不起作用。
您可能需要进一步考虑代码稳健性的一些方面;
当您将整数值变量存储为环境变量时,请尝试
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)
【讨论】:
myvar = int(os.environ.get('MYVAR')) if os.environ.get('MYVAR', '') != '' else None——如果没有提供数字,那就是 None
value_not_set = '-1')。然后,您可以使用debussy = int(os.environ.get('DEBUSSY', value_not_set))
os.environ 的行为类似于 python 字典,因此可以执行所有常见的字典操作。除了其他答案中提到的get 和set 操作之外,我们还可以简单地检查是否存在密钥。键和值应存储为字符串。
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不会反映最新的价值观。
摘自docs:
第一次导入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'>
【讨论】:
os.environ.data 在 Python 3.2 中被重命名为 os.environ._data,下划线前缀表明您不应该直接阅读它。无论如何,os.environ._data 无论如何都不会更新值。
在使用此方法之前,请浏览评论部分
我一直在尝试添加环境变量。我的目标是将一些用户信息存储到系统变量中,以便我可以将这些变量用于未来的解决方案,作为配置文件的替代方案。 但是,下面代码中描述的方法对我一点帮助都没有。
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 系统设置的环境变量选项卡中找到它们。上面的代码几乎没有达到我的目的。这个问题在这里讨论:variable save problem
os.environ.putenv(key, value)
又一次失败的尝试。所以,最后,我通过模仿包装在 os 包的系统类中的 windows shell 命令成功地将变量保存在窗口环境寄存器中。下面的代码描述了这次成功的尝试。
os.system("SETX {0} {1} /M".format(key, value))
我希望这对你们中的一些人有所帮助。
【讨论】:
setx 可以截断您的环境变量。如果你将它用于像PATH 变量这样重要的东西,当变量超过 1024 个字符时,你的整个现有环境配置将被破坏。也没有办法“撤消”它。不要使用它。甚至微软doesn't know better。
如果我做 os.environ["DEBUSSY"] = 1,它 抱怨说 1 必须是 字符串。
那就做吧
os.environ["DEBUSSY"] = "1"
我也想知道怎么读 python中的环境变量(在 脚本的后面部分)一旦我设置 它。
只需使用os.environ["DEBUSSY"],如
some_value = os.environ["DEBUSSY"]
【讨论】:
设置变量:
使用key的item赋值方法:
import os
os.environ['DEBUSSY'] = '1' #Environ Variable must be string not Int
获取或检查它是否存在,
因为 os.environ 是一个实例,您可以尝试对象方式。
方法一:
os.environ.get('DEBUSSY') # this is error free method if not will return None by default
将得到'1'作为返回值
方法二:
os.environ['DEBUSSY'] # will throw an key error if not found!
方法三:
'DEBUSSY' in os.environ # will return Boolean True/False
方法四:
os.environ.has_key('DEBUSSY') #last 2 methods are Boolean Return so can use for conditional statements
【讨论】:
os.environ["DEBUSSY"] = '1' 呢?环境变量总是字符串。
【讨论】:
【讨论】:
set [<name>=[<value>]],但它只适用于当前正在运行的进程。当我关闭 cmd 时它不存在,即使它打开其他程序也看不到它。
应该注意,如果您尝试将环境变量设置为 bash 评估,它不会存储您所期望的。示例:
from os import environ
environ["JAVA_HOME"] = "$(/usr/libexec/java_home)"
这不会像在 shell 中那样评估它,因此您将获得文字表达式 $(/usr/libexec/java_home),而不是获取 /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/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}")
【讨论】:
您可以使用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
【讨论】:
当您使用环境变量(添加/修改/删除变量)时,一个好的做法是在函数完成时恢复之前的状态。
您可能需要类似 question 中描述的 modified_environ 上下文管理器来恢复环境变量。
经典用法:
with modified_environ(DEBUSSY="1"):
call_my_function()
【讨论】:
如果环境中不存在变量,使用setdefault函数设置新变量。
确保将环境变量设置为字符串,而不是 int。否则会抛出TypeError。
import os
if not os.environ.get("DEBUSSY"):
os.environ.setdefault("DEBUSSY","1")
else:
os.environ["DEBUSSY"] = "1"
print(os.environ["DEBUSSY"])
【讨论】:
setdefault 方法就足够了。
有一个很好的开箱即用的 Python 解决方案,称为 pycrosskit。 它将创建对 Linux 和 Windows 都是持久的环境变量。
用法:
# Will Set Persistent Value for Variable in System
# * subkey works only for windows like file in folder
# * reg_path works only for windows as register path
SysEnv.set_var(name, value, subkey, reg_path=default_reg_path)
# Will Get Persistent Value for Variable in System
# * reg_path works only for windows as register path
# * delete, deletes key from environment and its subkeys after read
SysEnv.get_var(name, reg_path=default_reg_path, delete=False)
【讨论】:
如果您在使用 Flask 和 unittest 时遇到困难,请记住,如果您在任何方法之外设置变量,则在导入应用程序时会读取此变量。可能看起来微不足道,但可以避免一些人头疼。
例如,如果进入你的 Flask 单元测试你:
setUp方法中设置环境变量。app.test_client() 测试您的应用程序进入第二步的变量不会被第三步看到,因为当你执行第一步时,变量已经被读取了。
【讨论】:
我写了这个简洁的小context manager 用于设置仅在缩进块期间的变量:
import os
from contextlib import contextmanager
@contextmanager
def extended_env(new_env_vars):
old_env = os.environ.copy()
os.environ.update(new_env_vars)
yield
os.environ.clear()
os.environ.update(old_env)
使用示例(希望是跨平台的):
import subprocess
subprocess.run("echo $ENVTESTO %ENVTESTO%", shell=True)
with extended_env({"ENVTESTO": "17"}):
subprocess.run("echo $ENVTESTO %ENVTESTO%", shell=True)
subprocess.run("echo $ENVTESTO %ENVTESTO%", shell=True)
【讨论】: