将错误消息写入 Standard Error 而不是 Standard Output

目前,我们正在使用宏将所有输出写入终端。在大多数终端中,有两种输出:标准 输出 () 用于一般信息,标准错误 () 用于 错误消息。这种区别使用户能够选择将 成功将程序输出到文件,但仍将错误消息打印到 屏幕。println!stdoutstderr

宏只能打印到标准输出,因此我们有 使用其他内容打印为标准错误。println!

检查写入错误的位置

首先,让我们观察一下 打印的内容当前是怎样的 写入标准输出,包括我们想要写入的任何错误消息 标准错误。我们将通过重定向标准输出流来做到这一点 添加到文件中,同时故意导致错误。我们不会重定向标准 error 流,因此发送到 Standard Error 的任何内容都将继续显示在 屏幕。minigrep

命令行程序应将错误消息发送到标准错误 stream 的 API 中,这样即使我们将 标准输出流到文件中。我们的程序目前表现不佳: 我们即将看到它将错误消息输出保存到文件中!

为了演示此行为,我们将使用要将标准输出流重定向到的文件路径 output.txt 运行程序。我们不会 传递任何参数,这应该会导致错误:>

$ cargo run > output.txt

该语法告诉 shell 将标准输出的内容写入 output.txt 而不是 screen。我们没有看到我们所在的错误消息 期望打印到屏幕上,这意味着它必须以 文件。以下是 output.txt 包含的内容:>

Problem parsing arguments: not enough arguments

是的,我们的错误消息正在打印到标准输出。它远不止于此 对于将此类错误消息打印为标准错误非常有用,因此仅 成功运行的数据最终会进入该文件。我们会改变这种情况。

打印错误到标准错误

我们将使用示例 12-24 中的代码来更改错误消息的打印方式。 由于我们在本章前面所做的重构,所有 prints 错误消息 位于一个函数 中。标准库提供 打印到标准错误流的宏,因此让我们将 我们打电话来打印错误来代替使用的两个地方。maineprintln!println!eprintln!

文件名: src/main.rs
use std::env;
use std::process;

use minigrep::Config;

fn main() {
    let args: Vec<String> = env::args().collect();

    let config = Config::build(&args).unwrap_or_else(|err| {
        eprintln!("Problem parsing arguments: {err}");
        process::exit(1);
    });

    if let Err(e) = minigrep::run(config) {
        eprintln!("Application error: {e}");
        process::exit(1);
    }
}
示例 12-24:使用eprintln!

现在让我们以相同的方式再次运行程序,没有任何参数和 使用 重定向标准输出 :>

$ cargo run > output.txt
Problem parsing arguments: not enough arguments

现在我们在屏幕上看到错误,output.txt不包含任何内容,即 我们期望命令行程序的行为。

让我们使用不会导致错误但仍 将标准输出重定向到文件,如下所示:

$ cargo run -- to poem.txt > output.txt

我们不会看到终端的任何输出,output.txt将包含我们的 结果:

文件名: output.txt

Are you nobody, too?
How dreary to be somebody!

这表明我们现在正在使用标准输出来实现成功的输出 和 standard error 作为适当的错误输出。

总结

本章回顾了您到目前为止学到的一些主要概念,以及 介绍了如何在 Rust 中执行常见的 I/O作。使用命令行 参数、文件、环境变量和用于打印的宏 错误,您现在已准备好编写命令行应用程序。结合 前面章节中的概念,你的代码会组织得很好,存储数据 在适当的数据结构中有效地处理错误,并 经过充分测试。eprintln!

接下来,我们将探索一些受函数式 语言:闭包和迭代器。

本文档由官方文档翻译而来,如有差异请以官方英文文档(https://doc.rust-lang.org/)为准