我需要在 Python 脚本中设置一些环境变量,并且我希望从 Python 调用的所有其他脚本都可以看到环境变量的设置。
如果我做,
os.environ["DEBUSSY"] = 1
它抱怨说 1
必须是一个字符串。
我还想知道如何在 Python 中读取环境变量(在脚本的后半部分),一旦我设置了它。
环境变量必须是字符串,所以使用
os.environ["DEBUSSY"] = "1"
将变量 DEBUSSY
设置为字符串 1
。
要稍后访问此变量,只需使用:
print(os.environ["DEBUSSY"])
子进程自动继承父进程的环境变量——不需要您采取任何特殊行动。
您可能需要考虑代码稳健性的其他方面;
当您将整数值变量存储为环境变量时,请尝试
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
操作之外,我们还可以简单地检查一个键是否存在。键和值应存储为字符串。
蟒蛇 3
对于 python 3,字典使用 in 关键字而不是 has_key
>>> import os
>>> 'HOME' in os.environ # Check an existing env. variable
True
...
蟒蛇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"]
设置变量:
item 使用 key 的赋值方法:
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'
呢?环境变量始终是字符串。
您应该将字符串值分配给环境变量。
os.environ["DEBUSSY"] = "1"
如果您想读取或打印环境变量,只需使用
print os.environ["DEBUSSY"]
此更改仅对分配它的当前进程有效,不会永久更改值。子进程会自动继承父进程的环境。
https://i.stack.imgur.com/IHzb3.png
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
方法就足够了。
下面的呢?
os.environ["DEBUSSY"] = '1'
debussy = int(os.environ.get('DEBUSSY'))
print(type(debussy))
<类'int'>
我写了这个小 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)
示例用法(%
用于 Windows,$
用于 Linux):
import subprocess
subprocess.run("echo $ENVTEST %ENVTEST%", shell=True)
with extended_env({"ENVTEST": "17"}):
subprocess.run("echo $ENVTEST %ENVTEST%", shell=True)
subprocess.run("echo $ENVTEST %ENVTEST%", shell=True)
有一个很好的开箱即用的 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() 测试您的应用程序
进入第二步的变量不会被第三步看到,因为当你执行第一步时,变量已经被读取了。
管理用户定义的环境变量的一种巧妙方法是将它们全部放在一个文本文件中并在运行时加载它们。我们可以使用 python-dotenv 包来实现这一点,它允许我们导入这些变量。这个包可以通过安装
点安装 python-dotenv
默认情况下,模块会在当前目录中查找名为 .env 的文件。在此文件中定义所有变量,每行一个,如下所示:
DEBUSSY=1
PATH_TO_EXECUTABLE=/home/user_name/project/run.sh
然后将它们导入到您的环境中,如下所示:
from dotenv import load_dotenv
load_dotenv()
您可以将包含已定义变量的文件的路径指定为 load_dotenv 的可选参数。随后,这些环境变量就可以通过os模块正常访问了。
迟到的答案可能有助于某人在不更改代码的情况下快速测试。只需使用附加的环境变量运行您的应用程序,如下所示:
$ DEBUSSY=1 python3 api.py
您可以通过这种方式将环境变量传递给任何脚本。
putenv()
的 Unix 历史变体,但对于那些 Unixen,无论如何你无能为力。甚至我使用的旧版本的 AIX 和 HPUX 也支持它。如果今天真的有人能够找到不支持它的计算机,我非常怀疑他们是否能够在那台计算机上运行 Python。 :)import os
,否则这将不起作用。