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

Pho*_*b1a 9 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()
Run Code Online (Sandbox Code Playgroud)

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

这是我正在尝试做的django 文档

wim*_*wim 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')
Run Code Online (Sandbox Code Playgroud)

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


Mar*_*ark 6

如果您可以控制管理命令的代码,那么您应该遵循@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
Run Code Online (Sandbox Code Playgroud)

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

from os import devnull
stdout_backup, sys.stdout = sys.stdout, open(devnull, 'a')
...
Run Code Online (Sandbox Code Playgroud)