HOWTO · Python

在 Python 中将打印输出重定向到文件

本教程演示如何在 Python 中将打印输出重定向到文件

本页内容

在 Python 中将文本保存到文件,可以用 open() 打开文件,再通过返回的文件对象写入内容。使用 "w" 模式可创建或覆盖文件,使用 "a" 模式可在文件末尾追加内容。with 语句会在代码块结束时关闭文件。

下面的示例会将一条消息写入 report.txt,然后显示保存的文本:

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as folder:
    path = Path(folder) / "report.txt"
    with path.open("w", encoding="utf-8") as file:
        file.write("Monthly report\nRevenue: 1200\n")
    print(f"Saved to {path.name}:")
    print(path.read_text(encoding="utf-8"), end="")
Saved to report.txt:
Monthly report
Revenue: 1200

下面的示例说明何时使用 write()、print()、标准输出重定向、writelines() 或 pathlib 路径接口。大多数示例使用 with 语句自动关闭文件;sys.stdout 示例则会恢复先前的输出流,并显式关闭文件。

使用 open() 和 write() 写入文本

open() 用于选择打开文件的方式;write() 是其返回的文件对象上的方法。"w" 模式会创建文件或替换现有内容。"a" 模式会在文件不存在时创建文件,并在末尾追加文本。这些是打开文件时使用的模式,并不是 write() 的操作。

write() 接收字符串,但不会自动添加换行符。需要换行时,请加入 \n。返回值是写入的字符数。

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as folder:
    path = Path(folder) / "notes.txt"
    with path.open("w", encoding="utf-8") as file:
        file.write("First line\n")
        file.write("Second line\n")
    print(path.read_text(encoding="utf-8"), end="")
First line
Second line

若要追加内容,请将模式改为 "a"。例如,with open("notes.txt", "a", encoding="utf-8") as file: file.write("Next entry\n") 会在现有内容后添加一行。除非指定其他路径,否则该路径是相对于程序当前工作目录解析的。

使用 print() 将内容写入文件

如果想使用 print() 熟悉的格式化行为,同时将输出写入文件,可以使用 print(..., file=file_object)。它会将对象转换为文本,默认用空格分隔多个值,并默认在末尾添加换行符。可以通过 sep 和 end 修改这些设置。

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as folder:
    path = Path(folder) / "summary.txt"
    with path.open("w", encoding="utf-8") as file:
        print("Count:", 3, file=file)
        print("Ready:", True, file=file)
    print(path.read_text(encoding="utf-8"), end="")
Count: 3
Ready: True

打印完成后,with 代码块会关闭文件。在代码块中调用 close() 没有必要;代码块退出时,Python 会自动关闭文件。

使用 sys.stdout 重定向标准输出

未提供 file 参数时,print() 会使用 sys.stdout 输出。将文件赋给 sys.stdout 会重定向整个进程的标准输出,因此需要保存并恢复原来的输出流,同时关闭文件。若要在日常代码中进行有作用域限制的重定向,请优先使用下一节介绍的 contextlib.redirect_stdout()。请参阅sys.stdout 参考资料。目前没有对应的中文页面,此参考资料仅提供英文版本。

import sys
from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as folder:
    path = Path(folder) / "log.txt"
    previous_stdout = sys.stdout
    file = path.open("w", encoding="utf-8")
    try:
        sys.stdout = file
        print("Job complete")
    finally:
        sys.stdout = previous_stdout
        file.close()
    print(path.read_text(encoding="utf-8"), end="")
Job complete

在 finally 中恢复原来的输出流,可以确保后续输出回到先前的目标,即使重定向代码块中的代码发生错误也是如此。外层的 with 负责管理临时目录;恢复 sys.stdout 后,还会显式关闭文件。

使用 contextlib.redirect_stdout() 临时重定向输出

contextlib.redirect_stdout() 会在 with 代码块中暂时将 sys.stdout 指向一个类文件对象。代码块结束时,先前的标准输出流会恢复。文件仍由自身的 with 语句管理。

import contextlib
from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as folder:
    path = Path(folder) / "output.txt"
    with path.open("w", encoding="utf-8") as file:
        with contextlib.redirect_stdout(file):
            print("Build finished")
    print(path.read_text(encoding="utf-8"), end="")
Build finished

这种方式会捕获上下文代码块内的 print() 调用以及写入标准输出的其他内容,但不会重定向标准错误输出(sys.stderr)。

使用 writelines() 写入字符串序列

writelines() 会按顺序将可迭代对象中的每个字符串写入文件。它不会插入换行符;如果希望文件中的内容分成多行,请在字符串中加入 \n。

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as folder:
    path = Path(folder) / "items.txt"
    lines = ["apples\n", "pears\n", "plums\n"]
    with path.open("w", encoding="utf-8") as file:
        file.writelines(lines)
    print(path.read_text(encoding="utf-8"), end="")
apples
pears
plums

写入文本文件时,序列中的元素必须是字符串。如果不需要换行,请不要在字符串中加入 \n。

使用 pathlib 打开并写入文件

pathlib 提供用于构建和操作文件系统路径的对象。它不能取代文件对象:使用 Path.open() 获取文件对象,再调用它的 write() 方法。当路径由目录或其他路径部分组合而成时,这种方式很实用。

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as folder:
    path = Path(folder) / "archive" / "entry.txt"
    path.parent.mkdir()
    with path.open("w", encoding="utf-8") as file:
        file.write("Stored with pathlib.\n")
    print(path.read_text(encoding="utf-8"), end="")
Stored with pathlib.

如果不需要直接管理文件对象,可以使用 Path.write_text() 一步写入文本,写法更简洁。需要重复写入或使用 writelines() 等方法时,Path.open() 会提供可供操作的文件对象。

如果要执行相反的操作,请参阅如何在 Python 中将文件读入字符串。