Написання Повідомлень про Помилки у Помилковий Вивід замість Стандартного Виводу

Наразі ми записуємо увесь наш вивід в термінал використовуючи макрос println!. В більшості терміналів є два типи виводу: standard output (stdout) для загальної інформації та standard error (stderr) для повідомлень про помилки. Це розділення дозволяє користувачам направити вдалий вивід програми в файл, але все ще виводити повідомлення про помилки на екрані.

The println! macro is only capable of printing to standard output, so we have to use something else to print to standard error.

Перевірка Місця Написання Помилок

Спочатку, нумо побачимо, як контент який minigrep виводить в консолі наразі записується в стандартний вивід, включаючи будь-які повідомлення про помилки, які замість цього ми хочемо записувати в Standard Error. Ми зробимо це перенаправивши потік стандартного виводу в файл водночас із навмисним спричиненням помилки. Ми не будемо перенаправляти стандартний помилковій потік, тому будь-який контент відправлений в Standard Error буде продовжувати показуватися на екрані.

Очікується, що програми командного рядка надсилатимуть помилкові повідомлення в потік Standard Error, щоб ми все ще могли бачити помилкові повідомлення на екрані, навіть якщо ми перенаправляємо потік стандартного виводу в файл. Наразі наша програма не добре налаштована: ми побачимо, як вона збереже вивід помилкового повідомлення в файл натомість!

Щоб продемонструвати цю поведінку, ми запустимо програму з > і шляхом до файлу, output.txt, якому ми хочемо перенаправити потік стандартного виводу. Ми не будемо передавати аргументи, що спричинить помилку:

$ cargo run > output.txt

Синтаксис > вказує shell писати вміст стандартного виводу в output.txt замість екрана. Ми не бачимо помилкове повідомлення, яке ми очікували виведеним на екран, тому це означає, що воно опинилося в файлі. Це те, що містить output.txt:

Problem parsing arguments: not enough arguments

Так, наше помилкове повідомлення виводиться в консолі стандартного виводу. Це набагато корисніше для таких помилкових повідомлень, щоб вони виводилися в консолі Standard Error та щоб тільки дані від вдалих запусків опинялися в файлі. Ми змінимо це.

Виведення Помилок у Помилковий Вивід

Ми використаємо код в Блоці Коду 12-24 для зміни виводу помилкових повідомлень в консолі. Через рефакторінг, який ми робили раніше в цьому розділі, увесь код який виводить помилкові повідомлення перебуває в одній функції, main. Стандартна бібліотека надає макрос eprintln! який виводить в консолі потоку Standard Error, тому змінимо два місця, де ми викликаємо 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!

Це демонструє, що тепер ми використовуємо стандартний вивід для успішного виводу і стандартну помилку для виводу помилок у відповідних випадках.

Підсумок

В цьому розділі ми пригадали деякі основні концепти, які ви вивчили раніше та розглянули як виконувати базові I/O операції в Rust. Використовуючи аргументи командного рядка, файли, змінні середовища та макрос eprintln! для виведення помилок в консолі, тепер ви готові написати застосунок для командного рядка. Поєднавши це з концептами з попередніх розділів, ваш код буде добре організованим, ефективно збирати дані в відповідні структури даних, вдало обробляти помилки та буде добре перевіреним.

Далі ми детальніше розглянемо деякі функції Rust, на які вплинули функціональні мови: замикання та ітератори.