在Python中写入文件:重定向 vs print的file参数 vs write

6 投票
3 回答
9866 浏览
提问于 2025-04-16 06:30

我有很多 print 语句,我想把它们写入一个文件,而不是输出到屏幕上(我根本不需要屏幕输出)。

我考虑了三种方法。请问这三种方法有什么优缺点吗?(包括性能方面)

第一种是完全重定向,我在这里看到过:

import sys

saveout = sys.stdout
fsock = open('out.log', 'w')
sys.stdout = fsock

print(x)
# and many more print calls

# later if I ever need it:
# sys.stdout = saveout
# fsock.close()

第二种是在每个 print 语句中进行重定向:

fsock = open('out.log', 'w')
print(x, file = fsock)
# and many more print calls

第三种是写一个函数:

fsock = open('out.log', 'w')
fsock.write(str(x))
# and many more write calls

3 个回答

4

我觉得语义很重要:

我建议在你要打印的内容和在控制台上打印的内容一样时,使用第一种方法。这样语义是相同的。如果情况更复杂,我会使用标准的日志模块。

第二种和第三种方法在打印文本行时有点不同。第二种方法是,print会自动换行,而write则不会。

我主要在写二进制或非文本格式时会使用第三种方法,而在其他大多数情况下我会在打印语句中使用重定向。

4

从你提到的文件名来看,听起来你是想创建一个日志文件。你有没有考虑过使用Python的logging模块呢?

6

我觉得这几种方法在性能上不会有太大的差别。

第一种方法的好处是,你依赖的任何正常工作的代码(比如你引入的模块)都会自动使用你想要的输出重定向。

第二种方法没有什么好处。它只适合用来调试或者写一些临时的代码……但连这样做都不太好。你希望你的输出决策集中在几个明确的地方,而不是在每次调用print()时到处乱散。在Python3中,print()是一个函数,而不是一个语句。这让你可以重新定义它,如果你愿意的话。比如你可以用def print(*args)来定义自己的打印函数。如果你需要在自己定义的print()中访问原来的print(),你也可以调用__builtins__.print()

第三种方法……以及由此延伸出的原则是,所有的输出都应该在你为此目的定义的特定函数和类方法中生成……这可能是最好的选择。

你应该尽量把输出和格式化与核心功能分开。通过保持它们的分离,你可以让核心功能得到重用。(比如你可能一开始是想让它在文本/命令行控制台中运行,后来又需要提供一个网页界面、全屏(curses)前端或者图形用户界面。你也可能围绕它构建完全不同的功能……在某些情况下,结果数据需要以其原始形式(作为对象)返回,而不是作为文本(输出)然后重新解析成新对象。)

例如,我曾经遇到过好几次,我写的代码用来执行一些复杂的查询和从不同来源收集数据并打印报告……比如说不一致之处……后来需要调整成可以输出某种格式(比如YAML/JSON),以便可以输入到其他系统中(比如,用于对比两个数据源)。

如果从一开始就把主要操作与输出和格式化分开,那么这种适应就相对简单。否则就需要进行相当多的重构(有时几乎等同于完全重写)。

撰写回答