I need to set some environment variables in the Python script and I want all the other scripts that are called from Python to see the environment variables' set.
If I do,
os.environ["DEBUSSY"] = 1
it complains saying that 1
has to be a string.
I also want to know how to read the environment variables in Python (in the latter part of the script) once I set it.
-
3Related: How do I access environment variables from Python?Stevoisiak– Stevoisiak2018年03月16日 13:45:01 +00:00Commented Mar 16, 2018 at 13:45
20 Answers 20
Environment variables must be strings, so use
import os
os.environ["DEBUSSY"] = "1"
to set the variable DEBUSSY
to the string 1
.
To access this variable later, simply use
print(os.environ["DEBUSSY"])
Child processes automatically inherit the environment of the parent process -- no special action on your part is required.
-
76On some platforms, modifying os.environ will not actually modify the system environment either for the current process or child processes. See the docs for more info: docs.python.org/2/library/os.html#os.environEvan– Evan2016年04月21日 20:57:00 +00:00Commented Apr 21, 2016 at 20:57
-
21@Evan There might be some historical variants of Unix that don't support
putenv()
, but for those Unixen there is nothing you can do anyway. Even old version of AIX and HPUX I worked with did support it. If anyone is actually able to find a computer not supporting it today, I have severe doubts they will be able to run Python on that computer. :)Sven Marnach– Sven Marnach2016年04月21日 21:47:54 +00:00Commented Apr 21, 2016 at 21:47 -
14Caution: to quote from @Evan's reference above, Such changes to the environment affect subprocesses started with os.system(), popen() or fork() and execv(). In other words, keep in mind that this approach won't modify the way your program is running, only the way your program's children run. True, your program can set and read back environment variables, but only from the environment it configures for its children. See also: change current process environment. So far I haven't found a way for a Python script to modify its parent env.CODE-REaD– CODE-REaD2016年05月14日 16:55:31 +00:00Commented May 14, 2016 at 16:55
-
1@SvenMarnach is the statement "child process automatically inherit the environment of the parent process' true for shell like bash.Krishna– Krishna2017年01月13日 05:09:13 +00:00Commented Jan 13, 2017 at 5:09
-
21For any total noobs like me, you have to type
import os
first, or this won't work.Harry– Harry2020年11月18日 08:20:19 +00:00Commented Nov 18, 2020 at 8:20
You may need to consider some further aspects for code robustness;
when you're storing an integer-valued variable as an environment variable, try
os.environ['DEBUSSY'] = str(myintvariable)
then for retrieval, consider that to avoid errors, you should try
os.environ.get('DEBUSSY', 'Not Set')
possibly substitute '-1' for 'Not Set'
so, to put that all together
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)
-
3Can you tell how would set the variable on a Linux machine, is the code same for all platforms ?Anurag-Sharma– Anurag-Sharma2014年01月04日 16:11:14 +00:00Commented Jan 4, 2014 at 16:11
-
6It rarely makes sense to store -1 for a missing integer. A better bet would be
myvar = int(os.environ.get('MYVAR')) if os.environ.get('MYVAR', '') != '' else None
– that way it would be None if no number was providedBenjamin Atkin– Benjamin Atkin2019年05月07日 21:30:12 +00:00Commented May 7, 2019 at 21:30 -
1If you are dealing with integers, a -1 makes sense. Though I would likely set a variable/constant to the value I would use for not set (e.g.,
value_not_set = '-1'
). Then, you could usedebussy = int(os.environ.get('DEBUSSY', value_not_set))
yeOldeDataSmythe– yeOldeDataSmythe2019年11月01日 13:20:54 +00:00Commented Nov 1, 2019 at 13:20
os.environ
behaves like a python dictionary, so all the common dictionary operations can be performed. In addition to the get
and set
operations mentioned in the other answers, we can also simply check if a key exists. The keys and values should be stored as strings.
Python 3
For python 3, dictionaries use the in keyword instead of 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'
There is one important thing to note about using os.environ
:
Although child processes inherit the environment from the parent process, I had run into an issue recently and figured out, if you have other scripts updating the environment while your python script is running, calling os.environ
again will not reflect the latest values.
Excerpt from the docs:
This mapping is captured the first time the os module is imported, typically during Python startup as part of processing site.py. Changes to the environment made after this time are not reflected in os.environ, except for changes made by modifying os.environ directly.
os.environ.data
which stores all the environment variables, is a dict object, which contains all the environment values:
>>> type(os.environ.data) # changed to _data since v3.2 (refer comment below)
<type 'dict'>
-
8A process's environment variables are set when the process is created. Any changes made after this won't affect the process's own copy of the environment variable. This is common to all processes, not just Python. Further,
os.environ.data
was renamed in Python 3.2 toos.environ._data
, the underscore prefix showing that you shouldn't read it directly. Anyway,os.environ._data
won't have updated values anyway.Al Sweigart– Al Sweigart2018年07月31日 20:14:27 +00:00Commented Jul 31, 2018 at 20:14 -
Yep, I understand now. I wanted to share my initial surprise with others who come looking. Thanks for pointing out the update to the variable name since 3.2, will update the answer.sisanared– sisanared2018年08月01日 06:14:40 +00:00Commented Aug 1, 2018 at 6:14
-
? "
os.environ
behaves like a python dictionary, so all the common dictionary operations can be performed. In addition to the get and set operations mentioned..." It doesn't have a.set()
method, only a.setdefault()
smci– smci2022年11月09日 23:50:51 +00:00Commented Nov 9, 2022 at 23:50
Before using this method please go through Comments Sections
I have been trying to add environment variables. My goal was to store some user information to system variables such that I can use those variables for future solutions, as an alternative to config files. However, the method described in the code below did not help me at all.
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")
This simple code block works well, however, these variables exist inside the respective processes such that you will not find them in the environment variables tab of windows system settings. Pretty much above code did not serve my purpose. This problem is discussed here: variable save problem
os.environ.putenv(key, value)
Another unsuccessful attempt. So, finally, I managed to save variables successfully inside the window environment register by mimicking the windows shell commands wrapped inside the system class of os package. The following code describes this successful attempt.
os.system("SETX {0} {1} /M".format(key, value))
I hope this will be helpful for some of you.
-
19This is a very bad idea! The variable will be stored permanently in the system and you can only delete it by editing the registry! (HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment). You should at least warn people when you suggest such things! (But maybe you didn't even have an idea about that!)Apostolos– Apostolos2020年09月12日 06:49:29 +00:00Commented Sep 12, 2020 at 6:49
-
4Yes, adding a permanent variable is the idea here. I should have mentioned that. Thanks for the update. Methods described at the start of the answers do add env variables which exist in that process only, which is matter of choice, I needed a permanent save.Sourabh Desai– Sourabh Desai2020年09月12日 06:55:17 +00:00Commented Sep 12, 2020 at 6:55
-
3I don't think this is the idea at all. For one thing, the question or its description doesn't mention anything like that. Then, logically one assumes that the questioner wants to create just a persistent variable that can be used by other scripts, etc., not a permanent variable in the registry! Now, I admit I was aggressive in my comment, but you made me lost a lot of time until I find out how to remove a permanent a variable from the environment that I created just for testing!!Apostolos– Apostolos2020年09月12日 09:13:23 +00:00Commented Sep 12, 2020 at 9:13
-
8Its actually worse than just permanent registry storage.
setx
can truncate your environment variables. If you use it for something important like thePATH
variable, your entire existing environment configuration will get mangled when the variable is longer than 1024 characters. There is no way to 'undo' that either. Do not use it. Even Microsoft doesn't know better.Amit Naidu– Amit Naidu2021年03月12日 04:08:40 +00:00Commented Mar 12, 2021 at 4:08
if i do os.environ["DEBUSSY"] = 1, it complains saying that 1 has to be string.
Then do
os.environ["DEBUSSY"] = "1"
I also want to know how to read the environment variables in python(in the later part of the script) once i set it.
Just use os.environ["DEBUSSY"]
, as in
some_value = os.environ["DEBUSSY"]
to Set Variable:
item Assignment method using key:
import os
os.environ['DEBUSSY'] = '1' #Environ Variable must be string not Int
to get or to check whether its existed or not,
since os.environ is an instance you can try object way.
Method 1:
os.environ.get('DEBUSSY') # this is error free method if not will return None by default
will get '1'
as return value
Method 2:
os.environ['DEBUSSY'] # will throw an key error if not found!
Method 3:
'DEBUSSY' in os.environ # will return Boolean True/False
Method 4:
os.environ.has_key('DEBUSSY') #last 2 methods are Boolean Return so can use for conditional statements
What about os.environ["DEBUSSY"] = '1'
? Environment variables are always strings.
You should assign string value to environment variable.
os.environ["DEBUSSY"] = "1"
If you want to read or print the environment variable just use
print os.environ["DEBUSSY"]
This changes will be effective only for the current process where it was assigned, it will no change the value permanently. The child processes will automatically inherit the environment of the parent process.
-
7"This changes will be effective only for the current process where it was assigned, it will no change the value permanently. " This answered a question I had about the scope of setting an environ variable.spitfiredd– spitfiredd2017年05月07日 14:28:52 +00:00Commented May 7, 2017 at 14:28
-
2If I exit the python shell, and the os environmet set previously is gone.MeadowMuffins– MeadowMuffins2017年08月21日 07:05:09 +00:00Commented Aug 21, 2017 at 7:05
-
How do I set an environment variable in windows? I tried
set [<name>=[<value>]]
but it only makes it for the current running process. When I close the cmd it doesn't exist and even when it's open other programms can't see it.Filip– Filip2020年04月17日 08:42:08 +00:00Commented Apr 17, 2020 at 8:42
It should be noted that if you try to set the environment variable to a bash evaluation it won't store what you expect. Example:
from os import environ
environ["JAVA_HOME"] = "$(/usr/libexec/java_home)"
This won't evaluate it like it does in a shell, so instead of getting /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home
as a path you will get the literal expression $(/usr/libexec/java_home)
.
Make sure to evaluate it before setting the environment variable, like so:
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}")
Set Environment Variables like this :
import os
# Set environment variables
os.environ['API_USER'] = 'username'
os.environ['API_PASSWORD'] = 'secret'
# Get environment variables
USER = os.getenv('API_USER')
PASSWORD = os.environ.get('API_PASSWORD')
-
1How is this different from the first answer by Sven Marnach?sharhp– sharhp2024年03月12日 06:04:15 +00:00Commented Mar 12, 2024 at 6:04
You can use the os.environ
dictionary to access your environment variables.
Now, a problem I had is that if I tried to use os.system
to run a batch file that sets your environment variables (using the SET command in a **.bat* file) it would not really set them for your python environment (but for the child process that is created with the os.system
function). To actually get the variables set in the python environment, I use this script:
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
When you play with environment variables (add/modify/remove variables), a good practice is to restore the previous state at function completion.
You may need something like the modified_environ
context manager describe in this question to restore the environment variables.
Classic usage:
with modified_environ(DEBUSSY="1"):
call_my_function()
Use setdefault
function to set a new variable if the variable does not exist in the environment.
make sure you set the environment variable as a string, not int. Otherwise will throw TypeError
.
import os
if not os.environ.get("DEBUSSY"):
os.environ.setdefault("DEBUSSY","1")
else:
os.environ["DEBUSSY"] = "1"
print(os.environ["DEBUSSY"])
-
1Don't you need the if statement at all? I think just using
setdefault
method alone is enough.Smart Humanism– Smart Humanism2021年12月02日 19:25:47 +00:00Commented Dec 2, 2021 at 19:25
A neat way to manage user defined environment variables is to put all of them in a text file and load them at runtime. We can achieve this using the python-dotenv package, which allows us to import these variables. This package can be installed via:
pip install python-dotenv
By default the module looks for a file named .env in the current directory. Define all your variables in this file, one per line as follows:
DEBUSSY=1
PATH_TO_EXECUTABLE=/home/user_name/project/run.sh
And then import these to your environment as follows:
from dotenv import load_dotenv
load_dotenv()
print(os.getenv('DEBUSSY'))
You can specify the path to the file containing the defined variables as an optional argument to load_dotenv. Subsequently, these environment variables can be accessed via the os module as explained in some of the other responses.
I wrote this little context manager which sets variables for the duration of an indented block only:
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)
Example usage (with %
for Windows and $
for 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)
-
Or in Python 3.9+:
subprocess.run(..., env=os.environ | {"ENVTEST": "17"})
xjcl– xjcl2024年02月08日 15:44:29 +00:00Commented Feb 8, 2024 at 15:44
What about the following?
os.environ["DEBUSSY"] = '1'
debussy = int(os.environ.get('DEBUSSY'))
print(type(debussy))
<class 'int'>
There is good out of the box Python solution called pycrosskit. It will create environment variables that are persistent both for Linux and Windows.
Usage:
# 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)
-
The environment variables created this way do not seem to be persistent at all.Marcell– Marcell2021年12月16日 11:37:57 +00:00Commented Dec 16, 2021 at 11:37
Late answer that might help someone test fast without code changes. Just run your app with the environment variable attached as so:
$ DEBUSSY=1 python3 api.py
You can pass env vars this way to any script.
If you are struggling with Flask and unittest, please remember that if you set a variable outside any method, this variable is read when you import the app. Might seem trivial, but could save some headache to someone.
For example, if into your Flask unittest you:
- import the app
- set the environment variable in the
setUp
method. - use
app.test_client()
to test your application
The variable into the second step will not be seen by the third step, because the variable is already read when you perform the first step.
The environment is frozen for the code itself (not child processes) and cannot be accomplished with programmatically.
A good solution, no matter what platform, is to wrap the call to python in a batch file. For example: if I were on linux, the batch file might look like
export "DEBUSSY"="1"
python mycode.py