我一直在尝试使用这段代码重定向自定义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
答案 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()
我知道这是一个丑陋的解决方案,但这是我使其发挥作用的唯一方式。