How to Safely Add Environment Variables to your Python App
Tags: python
Published: 2019-12-12 03:53:07

---
title: How to Safely Add Environment Variables to your Python App
published: true
description: Need to use a secret key in your Python project? This tutorial shows you how to safely add environment variables without exposing your secrets to the world.
tags: python
canonical_url: https://taylorfacen.dev/tutorial/environment-variables.html
---

Picture this. You have some awesome code that you want to share with the world. However, you don't want to or can’t share keys, credentials, and other sensitive information. Sure we can add these items to our bash_profile, but what if we accidentally use a set of keys for the wrong project? This is where the dotenv family saves the day. The dotenv module loads credentials from a `.env` file, allowing you to customize the settings for each project individually. For this sample console project, we’ll be using [python-dotenv](https://pypi.org/project/python-dotenv/). There are also versions for [Node](https://github.com/motdotla/dotenv) and [Ruby](https://github.com/bkeepers/dotenv). 

## What we’re Building
[This commit](https://github.com/TaylorFacen/Console-Weather-App/tree/c67715559eec5254fd248b84f478d968d19a33d9) has the starter code to create an app that logs the weather to the console. The code is 99% done, and the only thing that’s left is to add the necessary API key to get it running. We’ll be using [Dark Sky](https://darksky.net/dev) to retrieve weather data. So grab a key and head on over to your favorite text editor.

## Let’s Code! 
As you can see in the starter files, the api key is listed in plain site.

```python
import requests

DARK_SKY_API_KEY = "my-super-secret-api-key"

def get_weather(latitude, longitude):
    url = "https://api.darksky.net/forecast/{}/{},{}".format(DARK_SKY_API_KEY, latitude, longitude)

    response = requests.get(url)
    data = response.json()

    current_weather = data['currently']
    summary = current_weather['summary'].lower()
    temperature = current_weather['temperature']

    message = "Currently, it's {} degrees outside. There's also {}".format(temperature, summary)
    print(message)


if __name__ == "__main__":
    get_weather(latitude = 37.8267, longitude = -122.4233)
```

![Funny gif](https://taylorfacen.dev/images/post-images/environment-variables/what-is-you-doin.gif)

The first step is to launch the virtual environment, install current dependencies, and install the `python-dotenv` package.

```
virtualenv env
source env/bin/activate
pip install -r requirements.txt
pip install python-dotenv
pip freeze > requirements.txt
```

Now that the package is installed, let's create a `.env` file with the following text.

```
DARK_SKY_API_KEY=ENTER-YOUR-DARKSKY-API-KEY-HERE
```

Any variables set in the .env file will be accessible in the app via `os`. Note that variables set here will override any variables set in your bash_profile. Meaning, if I have one value for my api key in my bash_profile and another set here for the same variable in the .env file, the value in the .env file will be used in the app. 

Now that the .env file is set up, I can update the `weather_app.py` file to look like the following

```python
from dotenv import load_dotenv
import os
import requests

load_dotenv()

DARK_SKY_API_KEY = os.environ['DARK_SKY_API_KEY']

def get_weather(latitude, longitude):
    url = "https://api.darksky.net/forecast/{}/{},{}".format(DARK_SKY_API_KEY, latitude, longitude)

    response = requests.get(url)
    data = response.json()

    current_weather = data['currently']
    summary = current_weather['summary'].lower()
    temperature = current_weather['temperature']

    message = "Currently, it's {} degrees outside. There's also {}.".format(temperature, summary)
    print(message)


if __name__ == "__main__":
    get_weather(latitude = 37.8267, longitude = -122.4233)
```

Make sure you add your `.env` file to the project's `.gitignore` file so that it doesn't get tracked in git history and sent to Github/ Bitbucket/ anywhere else. 

That's it! Running `python weather_app.py` shows that the app works! You can share your code with anyone without having to worry about them using your credentials. Here's what's logged out to my console.

```
Currently, it's 56.7 degrees outside. There's also overcast.
```

[Link to commit](https://github.com/TaylorFacen/Console-Weather-App/tree/e2dcfc09b9919989b7e1f922d1005cebe6f7f98d)

## Cleanup
Although the app works perfectly fine, I like to move all of my environment variable imports to a `config.py` file. This way, if multiple files need to reference the same value, I don't have to use dotenv across my entire app. 

Move the following code to a `config.py` file.

```python
from dotenv import load_dotenv
import os

load_dotenv()

DARK_SKY_API_KEY = os.environ['DARK_SKY_API_KEY']
```

Now, the top of the `weather_app.py` file only needs to contain the following lines of code:

```python
import requests

from config import DARK_SKY_API_KEY

def get_weather(latitude, longitude):
...
```

The app runs the same, but now it's a little cleaner and easier to expand on in the future. 

[Link to repo](https://github.com/TaylorFacen/Console-Weather-App)