How I Stopped Hardcoding Values in Python Scripts Using Enums

Table of Contents

As someone who writes Python scripts to automate daily tasks, I’m always searching for ways to make my code more reliable and readable. Recently, I discovered a tool that’s been a total game-changer for my scripts: Python Enums.

Let me share how using Enums helped me avoid silly bugs, made my code easier to understand, and can do the same for you!

The Problem: Magic Strings and Numbers Everywhere

When I first started automating tasks, I often used plain strings or numbers to represent options or states. For example:

def process_file(path, mode):
  if mode not in ("read", "write"):
    print("Unknown mode!")
    return
  if mode == "read":
    # ...read the file...
    pass
  elif mode == "write":
    # ...write to the file...
    pass

This works, but it’s easy to make mistakes. What if I accidentally type "reed" instead of "read"? Or what if someone else uses "READ"? These “magic strings” can lead to bugs that are hard to spot.

Enter Python Enums

One day, I stumbled upon Python’s Enum class. With Enums, you can define a set of named values—making your code safer and more self-explanatory.

Here’s how I refactored my function:

from enum import Enum, auto

class FileMode(Enum):
  READ = auto()
  WRITE = auto()

def process_file(path, mode: FileMode):
  if mode not in (FileMode.READ, FileMode.WRITE):
    print("Unknown mode!")
    return
  if mode == FileMode.READ:
    # ...read the file...
    pass
  if mode == FileMode.WRITE:
    # ...write to the file...
    pass

Now, instead of passing strings, I use FileMode.READ or FileMode.WRITE. If I try to pass something else, Python will complain—catching mistakes early.

Why I Love Enums

Switching to Enums made my scripts:

  • Safer: No more typos or invalid options sneaking in.
  • Clearer: Anyone reading my code instantly knows what values are allowed.
  • Easier to maintain: If I need to add a new mode, I just update the Enum.

Real-World Example from My Scripts

Before:

def run_etl_step(step):
    if step == "extract":
        print("Extracting data...")
        # ...extract logic...
        return
    if step == "transform":
        print("Transforming data...")
        # ...transform logic...
        return
    if step == "load":
        print("Loading data...")
        # ...load logic...
        return
    print("Unknown step.")

After (using Enum):

from enum import Enum, auto

class ETLStep(Enum):
    EXTRACT = auto()
    TRANSFORM = auto()
    LOAD = auto()

def run_etl_step(step: ETLStep):
    if step == ETLStep.EXTRACT:
        print("Extracting data...")
        # ...extract logic...
        return
    if step == ETLStep.TRANSFORM:
        print("Transforming data...")
        # ...transform logic...
        return
    if step == ETLStep.LOAD:
        print("Loading data...")
        # ...load logic...
        return
    print("Unknown step.")

Notice how the Enum version makes it much harder to pass an invalid step and is easier to maintain.

Now, my code is much harder to misuse—and much easier to read!

Final Thoughts

If you’re new to Python or automation, give Enums a try in your next script. They’ll help you avoid bugs, make your code more readable, and save you time in the long run. For me, this small change made a big difference in my daily workflow.

Happy coding!