[Fixed]-Redirect management.call_command() stdout to a file


Your command is probably just using print directly. To be able to capture or redirect prints in a management command, you’ll want to use the self.stdout handle of the command instance:

from __future__ import print_function

class Command(BaseCommand):

    def handle(self, *args, **options):
        # incorrect way to print in a management command:
        print('This line will go to the terminal')

        # correct ways to print in a management command:
        print('This line will go into the StringIO', file=self.stdout)
        self.stdout.write('This will also go into the StringIO')

If you’re unable change the print calls within the command (which is the code within 'basequery' in your example), then you can use a context manager to temporarily redirect stdout in order to capture that output. It’s important to restore the old stdout after redirection. See contextlib.redirect_stdout.



If you have control over the code of the management command, then you should follow the answer by @wim. This answer assumes you can’t/won’t change the command itself.

The method by @Igor is the best way when available, but some commands ignore stdout argument.

@Phob1a has a solution that is basically okay but has the problem of closing stdout (so future output to it doesn’t work). With some changes:

from django.core.management import call_command
import sys

stdout_backup, sys.stdout = sys.stdout, open('output_file', 'w+')
sys.stdout = stdout_backup

Note that if you want to just throw away output, you should replace the first command:

from os import devnull
stdout_backup, sys.stdout = sys.stdout, open(devnull, 'a')


I am using this to redirect output to file

    f = open('/path/to/file', 'w')
    buf = StringIO()
    call_command('compile_game_data', 'kingdom', indent=4, stdout=buf)


I tried Igor’s approximation using the following code:

class Command(BaseCommand):

    def handle(self, *args, **options):
        f = open('/tmp/output', 'w+')
        out = StringIO()
        management.call_command('basequery', 'list', 'log', stdout=out)

I got the same result tough: empty file and stdout appearing in the console. Maybe that’s because I’m calling django commands from a django command?

Anyway, I managed to solve the problem this way:

    sys.stdout = open('/tmp/output', 'w+')
    management.call_command('basequery', 'list', 'log')

I know it is an ugly solution but it’s the only way I made it work.


Leave a comment