【发布时间】:2020-02-10 17:32:46
【问题描述】:
在我的 Windows 10 场景中,我想将任意 python 控制台输出(print()、sys.exit() 等)打印到控制台和日志文件。我无法控制代码的某些部分(外部 python 包),所以我不能使用一些专用的日志记录机制。
经过一番研究,我在 UnxUtils 中找到了 tee.exe 工具,它几乎可以按照我想要的方式完成这项任务。
我的问题是保留由 python 的 colorama 包生成的颜色。有没有办法做到这一点?目前,tee.exe 会去除颜色。
我正在寻找的答案不必依赖 tee.exe,它只是我最接近真正解决方案的方法。我正在寻找的应该执行以下操作:
- 任何命令行输出都会同时出现在命令行和日志文件中(STOUT 和 STDERR)
- 输出实时显示在命令行上。如果日志文件也是如此,则加分。
- 颜色保留在命令行中。如果日志文件不包含任何与颜色相关的伪影,则可加分。
到目前为止,我所拥有的是:
Python 文件 teetest.py:
import sys
import colorama
print("Test")
print("2nd Test")
colorama.init(autoreset=True)
print(colorama.Fore.RED + 'Color Test')
colorama.deinit(autoreset=True)
sys.exit("Error_Test")
批处理文件teetest.bat:
@echo off
python teetest.py 2>&1 | tee log.txt
pause
我的输出看起来像这样(命令行和日志文件相同,没有颜色):
Test
2nd Test
Color Test
Error_Test
我正在寻找的解决方案会将上述内容打印到命令行,因此 Color Test 字样为红色。
编辑:
看来tee.exe 没有错。相反,colorama 会通过设计去除 ANSI 字符以进行颜色控制,因此在通过 tee.exe 时颜色会丢失。
来自色彩手册:
Colorama 通过包装标准输出、剥离它找到的 ANSI 序列(在输出中将显示为 gobbledygook)并将它们转换为适当的 win32 调用以修改终端的状态,也使这项工作在 Windows 上工作。
Colorama 的init() 函数提供参数strip,如果False,确实会导致colorama 不去除ANSI 字符。这反过来允许编写与tee.exe 相同的自定义tee.py,如下面的用户@martineau 所述。在其中,我们可以调用 colorama 并正确处理颜色。
这可能是一个可行的解决方案,但它仍然有一个缺点,即我必须在我的原始 python 代码中用 init(strip=False) 替换所有 colorama init() 调用,这反过来会导致 ANSI 字符出现在输出中如果代码在没有通过tee.py重定向的情况下被调用。
这实际上可能是我们可以在这里找到的最接近正确解决方案的地方。如果有人可以提供其他想法,我会全力以赴,但我担心机会渺茫。
【问题讨论】:
-
问个简单的问题:您假设
tee剥离了ANSI 序列,但您真的测试 了吗?coloramaitself 是终端感知的:“如果在 Windows 上或输出被重定向(不是 tty),默认行为是剥离。” github/colorama. -
@usr2564301。也许我没有正确表达这一点。我不认为
tee会去除 ANSI 序列,但实际上 colorama 会。请参阅我对 martineau 答案的评论。我打算将这些信息整合到原始帖子中,但还没有开始。一个解决方案可能是使用 colorama 的strip参数,但这会迫使我调整 python 代码,这是我想避免的。 -
如果您正在寻找对您的代码影响最小的更改,您可以随时将
https://github.com/tartley/colorama/blob/master/colorama/initialise.py的本地副本更改为默认清除strip。 -
@usr2564301 感谢您的想法。实际上,我以类似的方式研究了如何破解 colorama 并发现
strip使得它很容易做到。不管我是否通过tee管道输出,如果有一个选项以相同的方式工作,仍然会非常酷。不过,在这一点上,我希望渺茫。
标签: python windows tee colorama