Stop Hardcoding Values in Python Apps - Use JSON Configuration Files Instead

Stop Hardcoding Values in Python Apps - Use JSON Configuration Files Instead

Hardcoding Python app configuration is never a good idea. Try this alternative instead

App configuration changes. Backend databases can either migrate or change altogether. What happens to your Python app in that case? Well, it breaks. You have to update values in multiple Python files just to make the thing work again.

Configuration files provide an easy fix. There are multiple ways to work with configuration files in Python, and JSON is one of them. It likely isn’t the best one, at least not when compared to ini and yaml files. Still, it’s a viable method that is easy to set up, and you’ll learn all about it today.

Don’t feel like reading? Watch my video instead:


How to Write a JSON Configuration File for Python Apps

I’ve created a new folder with two files:

  • app.py - Contains Python code for today’s article.
  • config.json - Contains configuration data we don’t want to hardcode in Python.

We’ll communicate with a remote REST API today, so it makes sense for config.json to contain the API endpoint and local paths to where we’ll save the API response:

{
    "api": {
        "url": "https://gorest.co.in/public/v2/users"
    },
    "save": {
        "dir": "/Users/dradecic/Desktop/users_data",
        "file": "users.json"
    }
}

You can put pretty much anything inside config.json, as long as it’s properly formatted. Start with an object and declare a couple of keys that have objects for values.

Yes, it’s that easy. Let’s see next how to load this JSON configuration file in Python.


How to Use JSON Configuration File in Python Apps

Reading a JSON file in Python is best done with Python’s context manager syntax. To parse the contents of a JSON file to a Python dictionary, use the json.load() method:

import json
import pathlib
import requests


with open("config.json", "r") as f:
    config = json.load(f)
    
    
if __name__ == "__main__":
    print(config)

The entire configuration file is now loaded into memory. We can verify it by running app.py:

Image 1 - Printed Python JSON configuration file (image by author)

Image 1 - Printed Python JSON configuration file (image by author)

The variable config is now a plain Python dictionary object. You can access its elements either with bracket notation or with the get() method. We’ll use the prior today, but it’s just a personal preference.

We’ll now make a GET request to the API and provide a URL from the configuration file as an argument:

import json
import pathlib
import requests


with open("config.json", "r") as f:
    config = json.load(f)
    
    
def get_users() -> dict:
    r = requests.get(config["api"]["url"])
    return r.text
    
    
if __name__ == "__main__":
    print(get_users())

The function returns the contents of the response, which are the users in this case:

Image 2 - Users fetched from the REST API (image by author)

Image 2 - Users fetched from the REST API (image by author)

The last part of our mini data pipeline is saving the users locally. We already have both the directory name and file name in the configuration file - the only thing that remains is using them in Python.

Python’s pathlib module first creates the directory if it doesn’t exist. After that, we once again use the context manager syntax to dump the users to a JSON file:

import json
import pathlib
import requests


with open("config.json", "r") as f:
    config = json.load(f)


def get_users() -> dict:
    r = requests.get(config["api"]["url"])
    return r.text


def save_users(users: dict) -> None:
    path = pathlib.Path(config["save"]["dir"])
    if not path.exists():
        path.mkdir()

    with open(f"{config['save']['dir']}/{config['save']['file']}", "w") as f:
        json.dump(users, f)


if __name__ == "__main__":
    users = get_users()
    save_users(users=users)

After running the script, you’ll see users.json file saved locally to the earlier specified location:

Image 3 - Saved JSON file (image by author)

Image 3 - Saved JSON file (image by author)


Summary of JSON Configuration Files in Python

Hardcoding values is never a good idea. The above example was as simple as they come, sure, but imagine you had hundreds of Python files spread over multiple folders. Updating URLs and configurations manually would be a huge waste of time.

Today you’ve learned how to work with JSON configuration files in Python apps. The initial setup was easy, but there are a couple of downsides. For example, there’s no good way to put comments in JSON files. Also, you can’t use programming logic to determine variable values. All of these are shortcomings that will be addressed in future articles, so stay tuned.

Stay connected