将management.call_command()stdout重定向到文件

时间:2014-11-13 13:28:58

标签: python django

我一直在尝试使用这段代码重定向自定义django命令的标准输出:

from django.core.management.base import BaseCommand
from django.core import management


class Command(BaseCommand):

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

但是,当我从manage.py调用它时,控制台上会出现标准输出,并且/ tmp / output文件已创建但为空。

这是我正在尝试做的django documentation

4 个答案:

答案 0 :(得分:9)

您的命令可能只是直接使用print。为了能够在管理命令中捕获或重定向打印,您将需要使用命令实例的self.stdout句柄:

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')

如果您绝对无法更改命令的错误打印语句(在您的示例中是'basequery'命令中的代码中的错误),那么您可以使用上下文管理器临时重定向stdout以捕获该输出。重定向后恢复旧的stdout很重要。见contextlib.redirect_stdout

答案 1 :(得分:2)

如果您可以控制管理命令的代码,那么您应该遵循@wim的答案。这个答案假定你不能/不会改变命令本身。

@Igor的方法是可用的最佳方法,但有些命令会忽略stdout参数。

@ Phob1a有一个基本上没问题的解决方案但是有关闭stdout的问题(所以将来输出它不起作用)。有一些变化:

from django.core.management import call_command
import sys

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

请注意,如果您想丢弃输出,则应替换第一个命令:

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

答案 2 :(得分:0)

我使用它将输出重定向到文件

    f = open('/path/to/file', 'w')
    buf = StringIO()
    call_command('compile_game_data', 'kingdom', indent=4, stdout=buf)
    buf.seek(0)
    f.write(buf.read())
    f.close()

答案 3 :(得分:-2)

我使用以下代码尝试了Igor的近似值:

class Command(BaseCommand):

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

我得到了相同的结果:空文件和stdout出现在控制台中。也许那是因为我从django命令调用django命令?

无论如何,我设法以这种方式解决问题:

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

我知道这是一个丑陋的解决方案,但这是我使其发挥作用的唯一方式。