Django中call_command指定stdout无法拦截管理命令输出如何解决?
这个问题的核心原因是你写的import_stock自定义管理命令中,输出内容没有使用Django基类提供的输出方法,而是直接调用了Python内置的print()函数。call_command传入的stdout参数只会接管通过self.stdout.write(Django管理命令基类提供的标准输出方法)输出的内容,直接用print()会绕过该配置,直接输出到系统全局标准输出流,所以你的StringIO实例捕获不到任何内容。
方案一:修改自定义管理命令的输出逻辑(推荐)
找到你的import_stock命令的实现代码,把所有print()调用替换为self.stdout.write(),注意write()方法不会自动追加换行符,如果你需要和之前print()一致的效果,要手动补上\n:
# 替换前 print("Descriptions: 0 found, 0 not found, 0 not unique") # 替换后 self.stdout.write("Descriptions: 0 found, 0 not found, 0 not unique\n")
如果有错误提示类的输出,也可以用self.stderr.write()对应标准错误流,测试时如果要捕获这部分内容,调用call_command时额外传入stderr=你的StringIO实例即可。
方案二:全局拦截标准输出(无需修改命令代码)
如果你不方便修改已有的管理命令代码,可以直接接管系统级的标准输出流来捕获内容,修改你的测试代码中的do_command方法如下:
def do_command( self, *args, **kwargs): import sys from io import StringIO # 保存原标准输出对象 old_stdout = sys.stdout # 替换为自定义的StringIO实例 sys.stdout = capture_buf = StringIO() try: call_command(*args, **kwargs) return capture_buf.getvalue() finally: # 执行完后恢复原标准输出,避免影响其他测试 sys.stdout = old_stdout
额外注意点
你当前测试代码里的断言写的是self.assertIn('Stocklines: 0', text ),但实际命令输出的是首字母大写的StockLines:,大小写不一致也会导致断言失败,修改的时候注意对齐内容。
内容的提问来源于stack exchange,提问作者nigel222
相关产品推荐
相关产品推荐

