Adam Johnson

Home | Blog | Training | Projects | Colophon | Contact

How to Check the Running Django Command

2020-05-14

It’s occasionally useful to be able to tell which Django manage.py command is being run, in a code path that otherwise has no way of telling. For example, in Speed Up Your Django Tests, I describe how to modify manage.py to default use a test settings file when the test command is run.

The way to do this is to copy some of the parsing logic from inside Django, in ManagementUtility.execute(). This looks like:

import sys

try:
    command = sys.argv[1]
except IndexError:
    command = "help"

if command == "test":
    # Something specific to running "test"
    ...

While sometimes useful to change a default or add some instrumentation, I’d use this pattern with caution. Such changes will be hard to debug since they’re “at a distance.”

It’s normally possible to instead override another part of the given command. In particular, you can write a custom management command that imports and wraps the built-in one, as I showed in Make Django Tests Always Rebuild the Database if It Exists.

Warning: Incorrect sys.argv Checks

I’ve seen several a few community resources suggesting a similar pattern. However, rather than checking sys.argv[1] they check it with the in operator:

import sys


if "test" in sys.argv:  # WRONG!
    # Something specific to running "test"
    ...

This is imprecise. It will correctly set the default if you run python manage.py test, because then sys.argv will be ["manage.py", "test"]. But perhaps weeks, months, or years after you added this pattern and forgot about it, you might run a command like python manage.py delete-books --names test. Then sys.argv will be ["manage.py", "delete-books", "--names", "test"], so "test" will again be found, and the test-specific changes will accidentally be applied. This could back􏰀fire badly, so be careful.

Fin

Hope this helps you customize Django,

—Adam


Are your Django project's tests slow? Read Speed Up Your Django Tests now!


Subscribe via RSS, Twitter, or email:

One summary email a week, no spam, I pinky promise.

Related posts:

Tags: django, python