eprintln! și eprint! în Rust

Ca println! și print!, dar scriu pe ieșirea de eroare (stderr), separată de rezultatul normal al programului.

Sintaxă
eprintln!("Eroare: {}", mesaj);
eprint!("fără rând nou");

Ce face eprintln! și eprint!

Un program are două ieșiri de text: ieșirea standard (stdout), pentru rezultat, și ieșirea de eroare (stderr), pentru mesaje de eroare, avertismente și informații de progres. eprintln! și eprint! scriu pe stderr, cu aceeași sintaxă ca println! și print!.

În terminal ambele apar pe ecran, dar pot fi separate: program > rezultat.txt salvează doar stdout în fișier, iar erorile rămân vizibile pe ecran. Așa rezultatul nu este „murdărit” de mesaje. Ieșirea de eroare nu este tamponată, deci mesajele apar imediat.

Pe această pagină, rezultatul arată întâi tot ce s-a scris pe ieșirea standard și apoi ce s-a scris pe ieșirea de eroare; în terminal, rândurile apar în ordinea în care au fost scrise.

Exemple

Exemplul 1: Rezultat pe stdout, probleme pe stderr

Liniile valide sunt adunate și totalul este afișat cu println!. Linia invalidă este raportată cu eprintln!. Pe pagină, mesajul de eroare apare după total, pentru că este pe ieșirea de eroare.

fn main() {
    let linii = ["120", "45", "doi", "300"];
    let mut total = 0;
    for (nr, linie) in linii.iter().enumerate() {
        match linie.parse::<i32>() {
            Ok(n) => total += n,
            Err(e) => eprintln!("Linia {}: „{linie}” ignorată ({e})", nr + 1),
        }
    }
    println!("Total: {total} lei");
}

Rezultat

Total: 465 lei
Linia 3: „doi” ignorată (invalid digit found in string)

Exemplul 2: Separarea celor două ieșiri în terminal

Același program, rulat cu redirecționare. > total.txt trimite stdout în fișier, deci pe ecran rămâne doar mesajul de eroare. 2> erori.txt face invers.

$ cargo run -q > total.txt
$ cat total.txt
$ cargo run -q 2> erori.txt
$ cat erori.txt

Rezultat în terminal

Linia 3: „doi” ignorată (invalid digit found in string)
Total: 465 lei
Total: 465 lei
Linia 3: „doi” ignorată (invalid digit found in string)

Exemplul 3: Progres cu eprint!

Punctele de progres merg pe stderr, ca să nu se amestece cu rezultatul. Pe pagină apar după rezultat.

fn main() {
    eprint!("Calculez");
    let mut suma: u64 = 0;
    for i in 1..=1_000_000u64 {
        suma += i;
        if i % 250_000 == 0 {
            eprint!(".");
        }
    }
    eprintln!(" gata");
    println!("Suma 1..1.000.000 = {suma}");
}

Rezultat

Suma 1..1.000.000 = 500000500000
Calculez.... gata

Greșeli frecvente

  • Scrii mesajele de eroare cu println!: ajung în fișierul de rezultat când cineva redirecționează ieșirea (program > date.csv) și strică datele.
  • Te aștepți ca liniile de pe stdout și stderr să apară în ordine când ieșirile sunt redirecționate sau capturate de alt program. Sunt două canale separate; ordinea dintre ele nu este garantată.

Comenzi înrudite

  • println! și print!: Afișează text pe ieșirea standard: println! adaugă la final un rând nou, print! nu. Acoladele {} sunt înlocuite cu valori.
  • dbg!: Afișează rapid, pentru depanare, fișierul, linia, expresia și valoarea ei (în format Debug) pe stderr, apoi returnează valoarea.
  • panic!: Oprește firul de execuție curent cu un mesaj de eroare. Se folosește pentru situații care nu ar trebui să apară niciodată (bug-uri).
  • format! (și sintaxa de formatare): Construiește un String nou din șablon și valori, cu aceeași sintaxă ca println!, dar fără să afișeze nimic.