]> git.proxmox.com Git - rustc.git/blame - src/doc/book/second-edition/src/ch12-06-writing-to-stderr-instead-of-stdout.md
New upstream version 1.25.0+dfsg1
[rustc.git] / src / doc / book / second-edition / src / ch12-06-writing-to-stderr-instead-of-stdout.md
CommitLineData
3b2f2976 1## Writing Error Messages to Standard Error Instead of Standard Output
041b39d2 2
ff7c6d11 3At the moment we’re writing all of our output to the terminal using the
3b2f2976 4`println!` function. Most terminals provide two kinds of output: *standard
2c00a5a8 5output* (`stdout`) for general information and *standard error* (`stderr`)
ff7c6d11
XL
6for error messages. This distinction enables users to choose to direct the
7successful output of a program to a file but still print error messages to the
8screen.
041b39d2 9
ff7c6d11
XL
10The `println!` function is only capable of printing to standard output, so we
11have to use something else to print to standard error.
041b39d2 12
ff7c6d11 13### Checking Where Errors Are Written to
041b39d2 14
ff7c6d11
XL
15First, let’s observe how the content printed by `minigrep` is currently being
16written to standard output, including any error messages we want to write to
041b39d2 17standard error instead. We’ll do that by redirecting the standard output stream
ff7c6d11 18to a file while also intentionally causing an error. We won’t redirect the
041b39d2 19standard error stream, so any content sent to standard error will continue to
ff7c6d11
XL
20display on the screen.
21
22Command line programs are expected to send error messages to the standard error
23stream so we can still see error messages on the screen even if we redirect the
24standard output stream to a file. Our program is not currently well-behaved:
25we’re about to see that it saves the error message output to a file instead!
041b39d2
XL
26
27The way to demonstrate this behavior is by running the program with `>` and the
28filename, *output.txt*, that we want to redirect the standard output stream to.
ff7c6d11 29We won’t pass any arguments, which should cause an error:
cc61c64b
XL
30
31```text
32$ cargo run > output.txt
33```
34
3b2f2976 35The `>` syntax tells the shell to write the contents of standard output to
041b39d2 36*output.txt* instead of the screen. We didn’t see the error message we were
cc61c64b 37expecting printed on the screen, so that means it must have ended up in the
ff7c6d11 38file. This is what *output.txt* contains:
cc61c64b
XL
39
40```text
7cac9316 41Problem parsing arguments: not enough arguments
cc61c64b
XL
42```
43
3b2f2976 44Yup, our error message is being printed to standard output. It’s much more
ff7c6d11 45useful for error messages like this to be printed to standard error and have
3b2f2976 46only data from a successful run end up in the file when we redirect standard
ff7c6d11 47output this way. We’ll change that.
cc61c64b 48
041b39d2 49### Printing Errors to Standard Error
cc61c64b 50
ff7c6d11 51We’ll use the code in Listing 12-24 to change how error messages are printed.
041b39d2 52Because of the refactoring we did earlier in this chapter, all the code that
ff7c6d11
XL
53prints error messages is in one function, `main`. The standard library provides
54the `eprintln!` macro that prints to the standard error stream, so let’s change
55the two places we were calling `println!` to print errors to use `eprintln!`
56instead:
cc61c64b 57
041b39d2 58<span class="filename">Filename: src/main.rs</span>
cc61c64b 59
041b39d2 60```rust,ignore
cc61c64b
XL
61fn main() {
62 let args: Vec<String> = env::args().collect();
cc61c64b
XL
63
64 let config = Config::new(&args).unwrap_or_else(|err| {
041b39d2 65 eprintln!("Problem parsing arguments: {}", err);
cc61c64b
XL
66 process::exit(1);
67 });
68
041b39d2
XL
69 if let Err(e) = minigrep::run(config) {
70 eprintln!("Application error: {}", e);
cc61c64b
XL
71
72 process::exit(1);
73 }
74}
75```
76
3b2f2976
XL
77<span class="caption">Listing 12-24: Writing error messages to standard error
78instead of standard output using `eprintln!`</span>
cc61c64b 79
ff7c6d11
XL
80After changing `println!` to `eprintln!`, let’s run the program again in the
81same way, without any arguments and redirecting standard output with `>`:
cc61c64b
XL
82
83```text
84$ cargo run > output.txt
7cac9316 85Problem parsing arguments: not enough arguments
cc61c64b
XL
86```
87
ff7c6d11
XL
88Now we see the error onscreen and *output.txt* contains nothing, which is the
89behavior we expect of command line programs.
cc61c64b 90
ff7c6d11
XL
91Let’s run the program again with arguments that don’t cause an error but still
92redirect standard output to a file, like so:
cc61c64b
XL
93
94```text
95$ cargo run to poem.txt > output.txt
96```
97
ff7c6d11 98We won’t see any output to the terminal, and *output.txt* will contain our
cc61c64b
XL
99results:
100
101<span class="filename">Filename: output.txt</span>
102
103```text
104Are you nobody, too?
105How dreary to be somebody!
106```
107
ff7c6d11
XL
108This demonstrates that we’re now using standard output for successful output
109and standard error for error output as appropriate.
cc61c64b
XL
110
111## Summary
112
ff7c6d11
XL
113In this chapter, we’ve recapped some of the major concepts you’ve learned so
114far and covered how to do common I/O operations in a Rust context. By using
115command line arguments, files, environment variables, and the `eprintln!` macro
116for printing errors, you’re now prepared to write command line applications. By
117using the concepts in previous chapters, your code will be well organized,
118store data effectively in the appropriate data structures, handle errors
119nicely, and be well tested.
120
121Next, we’ll explore some Rust features that were influenced by functional
122languages: closures and iterators.