Dealing with Environment Variables in Flask
Tags: python, flask, security, environment
Published: 2021-08-10 16:00:05

Welcome to yet another article. Thanks for being a dedicated reader. More knowledge unto you, more skills learnt, and a better you. Before we begin on today's article, we will just have a brief recap of what we have learned over the course of time together.

![recap-image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3fe3c7avfr87u9k26n8a.png)

## What is Python?

Python is a widely-used, interpreted, object-oriented, and high-level programming language with dynamic semantics, used for general-purpose programming.
It was created by Guido van Rossum as a 'hobby' programming project. 

## Why do we love Python?

- Because it is an easy and intuitive language;
- Open source programming language. As a result, everyone may contribute to its growth;
- Code that is as simple to comprehend as plain English;
- Appropriate for day-to-day work, with quick development times

## What is Python used for?

Python has its application domains in many areas and these are but not limited to;

1. Web Applications
2. Data Science
3. Mobile Applications
4. Big Data
5. Artificial Intelligence
6. Automation 
7. Testing

To have a more detailed Introduction to Python, please feel free to check out this resource. [Python Basics, Pythons 101!](https://dev.to/kubona_my/python-basics-pythons-101-dj2)

Once that article has been read, we have a look at some concepts in Python worth remembering. These may not be explained exhaustively for beginners but gives a refresher to intermediate and expert python programmers. Even beginners can relate, good news!!

### Data Types

Literals are data whose values are decided by the literal itself, which Python provides out of the box. 

Common literals in Python include;
- Numeric literals
- Strings literals
- Special literal None
- Boolean literals
- Collection literals

In simple terms, literals are the raw data that are assigned to variables or constants while programming.

### Arithmetic operations in Python

Python supports out of the box support for arithmetic operations. With it you can perform these operations using expressions and operators. 

### Variables

 A variable is a named location reserved to store values in the memory.

Whenever you want to store results from operations, use a container called a *variable* to store them.  When naming variables, make sure you follow the **PEP Standards** defined here, [PEP 8 --Style Guide for Python Code](https://www.python.org/dev/peps/pep-0008/)

### Comments

Comments can be used to add more information to your code. At runtime, they are removed. Human readers are addressed by the information left in source code. A comment in Python is a line of text that starts with `#` for single line and `"""` for multi-line comments

### Functions

A function is a group of related statements that perform a given task. So whenever you call a function, those statements will perform that task, however many times you call the function.

Functions help us as programmers to;
- Avoid code repetitions
- Have cleaner and readable code
- Decompose large problems into small chunks. 

There are 3 major types of functions these are;

1. In-built functions
2. User defined functions
3. Pre-Installed module functions

For a more detailed guide on functions, please check out this resource. [Introduction to Python Functions](https://dev.to/kubona_my/introduction-to-python-functions-ije)

![Recap-done-image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ms0xa64zooklrcvzywes.png)


Great, welcome back from that recap about Python. Remember, the more you familiarize yourself with what Python is and how you use it, the better programmer you become at Python. 

> Every expert was once a beginner.

## Web development In Python

So one of the application domains of Python is **Web development**. You can use it to make powerful and fast web applications. In so making, a number of tools and frameworks have been developed to aid web development in Python. 

Some of these are but not limited to;

- Django
- Flask
- Pyramid

(*The picture below shows a list of web frameworks using Python*) 

![web-frameworks-python](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n4zmujxd51z3ne0de1e8.jpg)

Our focus will be on the Flask framework. For an Introduction to FLASK, please checkout their official documentation.
 [Official Flask Documentation](https://flask.palletsprojects.com/en/2.0.x/)

And for a quick overview on how to get started with Python Web development, consider looking into, [Getting Started with Python Web Development using FLASK](https://dev.to/grayhat/getting-started-with-python-web-development-1jl9)

Once you have mastered the basic overview of flask, we will dive into the topic of the day. Phew!!! What an introduction !!! Hope you are enjoying the article. Let us refocus now. 

![refocus-image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qvuk6gt4q5y404rw6lfs.png)

Given a minimal Flask application, such as;

```python

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World, dear Friend!'


@app.route('/page/<int:page_num>')
def content(page_num):
    return f'<h1>Yoo.. It is your page {page_num}</h1>'

if __name__ == '__main__':
    app.run(host='',port='',debug=True)

```

The minimal application can be run following the steps below, *(as you might be familiar)*, 

**On Bash**
```bash
export FLASK_APP=app.py
flask run
```

Other scenarios you might want to specify the host and port number, environment, debug mode etc.  for which you want your flask application to run, you would have to include all that into the `export command` above. 
That can become tedious over time as you develop your cool project, pressing up arrow key many times to retrace the export command (*bash users, you know what I mean*). 

Our goal is to save some time and when running our flask application, we simply do; 

**On Bash**
```bash
flask run
```

The variables that we add to the `export command` are known as **environment variables**. These variables are used by your flask application to serve your project. 

### Examples of environment variables include;

- FLASK_ENV
- FLASK_DEBUG.
- FLASK_RUN_EXTRA_FILES 
- FLASK_RUN_HOST
- FLASK_RUN_PORT 
- FLASK_RUN_CERT
- FLASK_RUN_KEY 

Those are default flask environment variables defined by the framework. If not specified, they use their default values.

### User defined variables

Also, if you wanted to connect your application to a database, you would have to hard code your credentials into your python code, **which is not recommended**. 
A simple example would be;

```python
from flask import Flask
app = Flask(__name__)

app.config[MYSQL_USER]="your_username"
app.config[MYSQL_HOST]="localhost"
app.config[MYSQL_DB]="my_appdb"
app.config[MYSQL_PASSWORD]="your_password"

@app.route('/')
def index():
    return {'Message': 'Hello World'}

```

**That kind of hard coding credentials is not ideal if you are working on a large project with other people**

Incase you do not follow *Strict password policies* and use one password everywhere....**You are hacked!!!**. You just shared your password with the world.

## So how do we deal with the **flask environment variables**?

We are going to see how to load flask environment variables automatically. You are here because you're tired of setting environment variables every time you are running your flask app? Variables like FLASK_APP or FLASK_ENV using `export command`. Am going to help you do just that.

### Step 1: Install python-dotenv

In your virtual environment, run;
```bash
pip install python-dotenv
```

I emphasize, always use virtual environments on your system to prevent corrupting your main Python installation. In case you want a recap on how to create virtual environments, refer to this guide. [Creation of Virtual Environments](https://docs.python.org/3/library/venv.html)

### Step 2: Create `.env` and `.flaskenv` files in your project root folder

**On Bash**
```bash
touch .env
touch .flaskenv
```

### Step 3: Place your flask environment variables in .flaskenv

Depending on your use case, this will guide you on what to include.

**In .flaskenv**
``` bash
//this is the .flaskenv file
FLASK_ENV - Controls the environment.
FLASK_DEBUG - Enables debug mode.
FLASK_RUN_EXTRA_FILES - A list of files that will be watched by the re-loader in addition to the Python modules.
FLASK_RUN_HOST - The host you want to bind your app to.
FLASK_RUN_PORT - The port you want to use.
FLASK_RUN_CERT - A certificate file for so your app can be run with HTTPS.
FLASK_RUN_KEY - The key file for your cert.
```
for example; `FLASK_APP=app.py`

Boom, great work done. To run your app now, Simply do run;

![flask-run](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p5nayohyahnarf80y82f.png)

That was fast,.... right?? Yes so you can now focus on programming instead of looking for which flask environment variable is missing.

## So how about **my-secretly-defined environment variables**?

Yes getting to that now. Follow this guide.

### Step 1. Place `your-secretly-defined environment variables` in `.env`

These can include;
- Login credentials to the database
- API keys
- SECRET_KEY
*(among others)*

**In .env**
``` bash
//This is the .env file
MYSQL_USER=root
MYSQL_PASSWORD=my_mysql_password
MYSQL_DB=userdb
MYSQL_HOST=localhost
SECRET_KEY=topsecretkey
API_KEY=donotsharethisapikeywithanyone

```

### Step 2: Create a settings.py file

(*Since these variables are not served automatically, we have to load them through this `settings.py` file*)

**In settings.py**
``` bash
//This is the settings.py file

from os import environ
SECRET_KEY=environ.get('SECRET_KEY)
API_KEY=environ.get('API_KEY')
MYSQL_USER=environ.get('MYSQL_USER')
//add any more variables you have

```
**Note**: For consistency, it is good to keep the same variable name as the environment variable.

### Step 3: Add the configurations to our app

In your `app.py` , the file that has your flask object.

```python
app.config.from_pyfile('settings.py')
# loading all environment variables from settings.py
```

So what happens is that the settings.py will read the values you placed in your .env file and store them in variables as you defined them in settings.py.

When you use the flask object's config method, together with the `from_pyfile` sub-method, the app will have access to the secretly defined variables in a secure way.

Run your app as before, and boom you can now serve the world with your cool project


### Bonus Tip:

To avoid surbotaging your efforts to secure your credentials, when using a version control system such as **git** , do not push the *.flaskenv* and *.env* files. You can use *.gitignore* file to ignore them in your project directory. They remain on your local system.

## How was the article?
I love to learn with you dear reader. Share your feedback with me in the discussion section below. Are there better ways to do this?
A great friend improves another, feel free to share 
I appreciate all the feedback in advance.


<img width="100%" style="width:100%" src="https://media.giphy.com/media/u3axz3PUbjJpQeysaP/giphy.gif">