How to Check the Running Django Command

Owl check what command is running

Update (2022-02-07): I’ve updated the post with a better way of checking the second element from sys.argv that I found in a Django codebase.

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 check the second element of sys.argv, which is what Django’s ManagementUtility.execute() does. You can do this succinctly like:

import sys

if sys.argv[1:2] == ["test"]:
    # Something specific to running "test"
    ...

This code works even when sys.argv has fewer than two elements, because slicing beyond the end of a list returns an empty list.

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 exactly 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 backfire badly, so avoid this pattern.

Fin

Hope this helps you customize Django,

—Adam


Learn how to make your tests run quickly in my book Speed Up Your Django Tests.


Subscribe via RSS, Twitter, Mastodon, or email:

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

Related posts:

Tags: ,