- Introduction
- The os Module
- Creating Environment Variables
- Getting Environment Variables With The OS Module
- Conclusion
- References
Introduction
Environment variables are used in a program to set the values of variables or constants within that program. The environment variables exist at the operating system level. This allows for the environment variables to be fluid in that they can be changed for different stages of the software development lifecycle without storing / changing the values in the source code for each stage (dev / test / production).
From a security perspective, it means that the source code does not have the values of its variables hard-coded into them. An example of this would be storing an API key as an environment variable instead of setting the value in a variable / constant in the source code. If that happened and was then sent up to a public (or even a private) Git repository, that would be a major security threat.
The os Module
For Python to interact with the operating system, the os
module is used. It can perform actions such as:
- Creating and reading environment variables.
- Getting details about the operating system, such as the type of operating system it is.
- Working with files and file paths.
There are a lot more that it can do, which is covered in the modules documentation.
So how can environment variables be created and used?
Creating Environment Variables
First up, let's create some environment variables to work with. There are multiple ways to do this, but this article will focus on two. The first of which is to create them via the operating system with the second being via Python using os.environ
.
Three example environment variables will be created, each with a different data type.
For both methods:
- EXAMPLE_ONE is just a string of text. This is a typical use case for most data that would be assigned to an environment variable.
- EXAMPLE_TWO is a number. Or is it? More on that later.
- EXAMPLE_THREE is a boolean. Or perhaps not. Again, more on that later.
Method One: Creating Environment Variables Via The Operating System
NOTE: On Linux / macOS, if the string has spaces in it, the string will need to be wrapped in ""
, otherwise only the text up to the first space will be assigned. Windows is fine without them.
Linux and macOS
Using a terminal emulator app, run:
export EXAMPLE_ONE="This is an environment variable"
export EXAMPLE_TWO=1
export EXAMPLE_THREE=False
If an environment variable needs to be persistent for Linux or macOS, it will need to be added to the users .bashrc
or .zshrc
file in their home directory using the same syntax.
Windows
Using the command prompt (cmd.exe), run:
set EXAMPLE_ONE=This is an environment variable
set EXAMPLE_TWO=1
set EXAMPLE_THREE=False
To set persistent environment variables in Windows, use the setx
command with the syntax being:
setx EXAMPLE_ONE "This is an environment variable"
setx EXAMPLE_TWO "1"
setx EXAMPLE_THREE "False"
Method Two: Creating Environment Variables Using Python
For all three operating system types, the method is the same in Python by using os.environ
:
import os
os.environ["EXAMPLE_ONE"] = "This is an environment variable"
os.environ["EXAMPLE_TWO"] = "1"
os.environ["EXAMPLE_THREE"] = "False"
NOTE: When Python is closed, these environment variables will be removed.
Getting Environment Variables With The OS Module
There are two methods that can be used to access an environment variable using the os
module. The first method is via os.environ
. It requires the environment variable name to be passed to it in a list. For example:
import os
print(os.environ["EXAMPLE_ONE"])
Output:
This is an environment variable
There is one downside to this method, which is open to interpretation. If the environment variable is not present, it will raise a KeyError
and cause a hard stop. An example of this is shown below:
Traceback (most recent call last):
File "/Users/neil/Documents/writing/blog-posts/code.py", line 11, in <module>
print(os.environ["EXAMPLE_ONE"])
~~~~~~~~~~^^^^^^^^^^^^^^^
File "<frozen os>", line 679, in __getitem__
KeyError: 'EXAMPLE_ONE'
Now, this might be what is required to happen, which is fine. But let's say that it isn't and the code needs to continue. To get around this, os.getenv
is a useful solution. What this will do is instead of erroring out, it will set the value to None
for any missing environment variables instead.
For the examples going forward, the os.getenv
method will be used.
Example One: Working With A String
The first example will get the value or the EXAMPLE_ONE
environment variable and show its value.
import os
example_one = os.getenv("EXAMPLE_ONE")
print(f"Example One Value: {example_one}")
print(type(example_one))
Output:
Example One Value: This is an environment variable
<class 'str'>
From the output, the value of example_one
is shown and it has a data type of str
(string).
Example Two: Working With A Number
This is where things get problematic. Remember how Example Two was described earlier ("EXAMPLE_TWO is a number. Or is it?"). Well, although it looks like a number, it is actually a string data type. This is because environment variables are treated as strings, no matter what the value is.
For example, let's access the EXAMPLE_TWO
environment variable and see what data type it has:
import os
example_two = os.getenv("EXAMPLE_TWO")
print(f"Example Two Value: {example_two}")
print(type(example_two))
Output:
Example Two Value: 1
<class 'str'>
As can be seen, the data type class is str
(string). So how can the value be used as a number, in this case an integer? It is done by enforcing the data type to the example_two
variable using the int
class. For example:
import os
example_two = int(os.getenv("EXAMPLE_TWO"))
print(f"Example Two Value: {example_two}")
print(type(example_two_int))
Output:
Example Two Value: 1
<class 'int'>
The output looks the same but the data type for example_two
is now an integer (int). This will now allow it to be used for any mathematical operations.
There is one further issue. What if the environment variable is not an integer number but rather a string, float, boolean or just doesn't exist?
If it doesn't exist, the value would be set to None
. If it did exist and is not an integer, it would be set to that value. But, as the data type is enforced as an integer, a ValueError
would be raised for both cases.
A solution for this would be to use the try
block to check it.
The following example will check the value of EXAMPLE_TWO
and if it can't be set to an integer data type due to the value not being an integer, it will set example_two
to 0
:
First, change EXAMPLE_TWO
to a non-number-based value:
Operating system method:
export EXAMPLE_TWO="I am not a number"
Or via Python:
import os
os.environ["EXAMPLE_TWO"] = "I am not a number"
Next, use the try
block to check and set the value of example_two
:
import os
try:
example_two_int = int(os.getenv("EXAMPLE_TWO"))
except ValueError:
example_two_int = 0
print(f"Example Two Value: {example_two_int}")
print(type(example_two_int))
Output:
Example Two Value: 0
<class 'int'>
As EXAMPLE_TWO
was not a numeric value, a ValueError
was raised and as a result, the value of example_two
was set to 0
.
Example Three: Working With A Boolean
Just as in example two, an environment variable with what looks like a boolean value will have a string data type. This will mean that it cannot be used for boolean operations.
One of the additional issues with boolean values is how they can be presented. For example, in Python a boolean value is set to either True
or False
. In other languages, such as JavaScript, they are set to either true
or false
. There are others, such as yes / no, y / n, 0 / 1 or on / off.
So, how can we set a boolean data type when there are a lot of possible ways that an environment variable can be set with a boolean value? This is actually easy to do with Python. Start by putting as many of the possible ways to present a True
value in a list and compare the value that is assigned to the environment variable. If the value matches one of the entries in the list, the value of the variable will be set to True
. If not, it will be False
.
For example, set a False
boolean value:
import os
example_three = os.getenv("EXAMPLE_THREE") # --- Currently set to "False"
example_three = example_three.lower() in ["true", "1", "1.0", "y", "yes", "on"]
print(f"Example Three Value: {example_three}")
print(type(example_three))
Output:
Example Three Value: False
<class 'bool'>
In the above example, the value of example_three
was converted to all lowercase to make it easier to check against and then compared to each entry in the list. As it didn't match, the new value of example_three
is False
but with a data type class of bool
, which is what is needed.
Conclusion
I hope that this article was useful. There will be a follow up article to this that will cover using .env files for creating environment variables.
Thank you for reading and have a nice day!
Top comments (0)