ChatGPT解决这个技术问题 Extra ChatGPT

如何在 Python 中设置环境变量?

我需要在 Python 脚本中设置一些环境变量,并且我希望从 Python 调用的所有其他脚本都可以看到环境变量的设置。

如果我做,

os.environ["DEBUSSY"] = 1

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

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


p
phoenix

环境变量必须是字符串,所以使用

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

将变量 DEBUSSY 设置为字符串 1

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

print(os.environ["DEBUSSY"])

子进程自动继承父进程的环境变量——不需要您采取任何特殊行动。


在某些平台上,修改 os.environ 并不会真正修改当前进程或子进程的系统环境。有关详细信息,请参阅文档:docs.python.org/2/library/os.html#os.environ
@Evan 可能有一些不支持 putenv() 的 Unix 历史变体,但对于那些 Unixen,无论如何你无能为力。甚至我使用的旧版本的 AIX 和 HPUX 也支持它。如果今天真的有人能够找到不支持它的计算机,我非常怀疑他们是否能够在那台计算机上运行 Python。 :)
注意: 引用@Evan 上面的引用,对环境的此类更改会影响以 os.system()、popen() 或 fork() 和 execv() 启动的子进程。 换句话说,请记住,这种方法不会修改程序的运行方式,只会修改程序子程序的运行方式。诚然,您的程序可以设置和读取环境变量,但只能从它为其子项配置的环境中设置和读取。另请参阅:change current process environment。到目前为止,我还没有找到一种让 Python 脚本修改其父环境的方法。
@SvenMarnach 是声明“子进程自动继承父进程的环境”对于像 bash 这样的 shell 是正确的。
对于像我这样的菜鸟,您必须先输入 import os,否则这将不起作用。
M
Mark

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

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

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)

你能告诉如何在 Linux 机器上设置变量,所有平台的代码都相同吗?
为丢失的整数存储 -1 几乎没有意义。更好的赌注是 myvar = int(os.environ.get('MYVAR')) if os.environ.get('MYVAR', '') != '' else None - 如果没有提供数字,那就是 None
如果您正在处理整数,则 -1 是有意义的。虽然我可能会将变量/常量设置为我将用于未设置的值(例如,value_not_set = '-1')。然后,您可以使用 debussy = int(os.environ.get('DEBUSSY', value_not_set))
s
sisanared

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

蟒蛇 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'>

进程的环境变量是在创建进程时设置的。在此之后所做的任何更改都不会影响进程自己的环境变量副本。这对所有进程都是通用的,而不仅仅是 Python。此外,os.environ.data 在 Python 3.2 中被重命名为 os.environ._data,下划线前缀表明您不应该直接阅读它。无论如何,os.environ._data 无论如何都不会有更新的值。
是的,我现在明白了。我想与其他前来寻找的人分享我最初的惊喜。感谢您指出自 3.2 以来对变量名称的更新,将更新答案。
S
Sourabh Desai

在使用此方法之前,请浏览评论部分

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

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))

我希望这对你们中的一些人有所帮助。


这是一个非常糟糕的主意!该变量将永久存储在系统中,您只能通过编辑注册表将其删除! (HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment)。当您提出此类建议时,您至少应该警告人们! (但也许你甚至对此一无所知!)
是的,这里的想法是添加一个永久变量。我应该提到这一点。感谢更新。答案开头描述的方法确实添加了仅存在于该过程中的环境变量,这是选择问题,我需要永久保存。
我认为这根本不是想法。一方面,这个问题或其描述没有提到任何类似的东西。然后,逻辑上假设提问者只想创建一个可以被其他脚本等使用的持久变量,而不是注册表中的永久变量!现在,我承认我的评论很激进,但是你让我浪费了很多时间,直到我发现如何从我为测试而创建的环境中删除一个永久变量!
它实际上比永久注册表存储更糟糕。 setx 可以截断您的环境变量。如果您将它用于诸如 PATH 变量之类的重要内容,则当变量超过 1024 个字符时,您的整个现有环境配置将被破坏。也没有办法“撤消”它。不要使用它。甚至微软doesn't know better
J
Jim Brissom

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

然后做

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

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

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

some_value = os.environ["DEBUSSY"]

M
Mohideen bin Mohammed

设置变量:

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

T
ThiefMaster

os.environ["DEBUSSY"] = '1' 呢?环境变量始终是字符串。


R
RejeeshChandran

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

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

如果您想读取或打印环境变量,只需使用

print os.environ["DEBUSSY"]

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

https://i.stack.imgur.com/IHzb3.png


“此更改仅对分配它的当前进程有效,不会永久更改值。” 这回答了我关于设置环境变量的范围的问题。
如果我退出 python shell,之前设置的 os environmet 就消失了。
如何在windows中设置环境变量?我试过 set [<name>=[<value>]] 但它只适用于当前正在运行的进程。当我关闭 cmd 时它不存在,即使它打开其他程序也看不到它。
J
Josh Correia

应该注意的是,如果您尝试将环境变量设置为 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}")

P
Paolo

您可以使用 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

C
Community

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

您可能需要类似于此 question 中描述的 modified_environ 上下文管理器来恢复环境变量。

经典用法:

with modified_environ(DEBUSSY="1"):
    call_my_function()

S
Sabuhi Shukurov

如果环境中不存在变量,则使用 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"])


你根本不需要 if 语句吗?我认为仅使用 setdefault 方法就足够了。
R
Romeo Kienzler

下面的呢?

os.environ["DEBUSSY"] = '1'
debussy = int(os.environ.get('DEBUSSY'))
print(type(debussy))

<类'int'>


x
xjcl

我写了这个小 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)

J
Jiri Otoupal イり オトウパー

有一个很好的开箱即用的 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)

以这种方式创建的环境变量似乎根本不持久。
A
Andrea

如果您在使用 Flask 和 unittest 时遇到困难,请记住,如果您在任何方法之外设置变量,则在导入应用程序时会读取此变量。可能看起来微不足道,但可以避免一些人头疼。

例如,如果进入你的 Flask 单元测试你:

导入应用在setUp方法中设置环境变量。使用 app.test_client() 测试您的应用程序

进入第二步的变量不会被第三步看到,因为当你执行第一步时,变量已经被读取了。


s
sharhp

管理用户定义的环境变量的一种巧妙方法是将它们全部放在一个文本文件中并在运行时加载它们。我们可以使用 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模块正常访问了。


L
Lucas

迟到的答案可能有助于某人在不更改代码的情况下快速测试。只需使用附加的环境变量运行您的应用程序,如下所示:

 $ DEBUSSY=1 python3 api.py

您可以通过这种方式将环境变量传递给任何脚本。