Rust 如何将输出发送到stderr?

Rust 如何将输出发送到stderr?,rust,stdio,Rust,Stdio,可以使用此命令将输出发送到标准输出: println!("some output") 我认为没有相应的宏可以对stderr执行相同的操作。它是这样做的: use std::io::Write; fn main() { std::io::stderr().write(b"some output\n"); } 您可以通过将程序输出发送到/dev/null来测试它,以确保它正常工作(我忽略警告): 同样,可以对标准输出执行以下操作: use std::io::Write; fn mai

可以使用此命令将输出发送到标准输出:

println!("some output")
我认为没有相应的宏可以对stderr执行相同的操作。

它是这样做的:

use std::io::Write;

fn main() {
    std::io::stderr().write(b"some output\n");
}
您可以通过将程序输出发送到
/dev/null
来测试它,以确保它正常工作(我忽略警告):

同样,可以对标准输出执行以下操作:

use std::io::Write;

fn main() {
    std::io::stdout().write(b"some output\n");
}
我想这意味着
println
只是一种方便:它更短,还允许一些格式。作为后者的示例,以下显示
0x400

println!("0x{:x}", 1024u)
和是写入标准输出的方便方法。其他宏具有相同的格式设置功能,可用于不同的任务:

  • 以及将格式化字符串写入
    &mut
  • 仅生成格式化的
    字符串
要写入标准错误流,您可以使用例如
writeln如下所示:

use std::io::Write;

fn main() {
    let mut stderr = std::io::stderr();
    writeln!(&mut stderr, "Error!").unwrap();
}
锈后1.19 从Rust 1.19开始,您可以使用和宏:

这最初是在年提出的

锈前1.19 你可以看到我们需要深入了解它是如何工作的,但当我第一次读到它时,它有点让人不知所措

您可以使用类似的宏将内容格式化为stderr:

use std::io::Write;

let name = "world";
writeln!(&mut std::io::stderr(), "Hello {}!", name);
这将给您一个必须使用的
未使用结果
警告,因为打印到IO可能会失败(这不是我们通常在打印时考虑的问题!)。我们可以看到本例中的现有方法,因此我们可以更新代码以执行相同的操作:

use std::io::Write;

let name = "world";
let r = writeln!(&mut std::io::stderr(), "Hello {}!", name);
r.expect("failed printing to stderr");
这有点多,所以让我们用一个宏来包装它:

use std::io::Write;

macro_rules! println_stderr(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

fn main() {
    let name = "world";
    println_stderr!("Hello {}!", name)
}
目标 笔记 其他答案会生成一个最新的夜间未使用导入警告,所以这里有一个现代的宏可以正常工作

代码
虽然没有回答准确的问题,但可能有一个
日志
板条箱指定了一个接口,用于其他板条箱(例如
环境日志
)可以实现的水平日志记录

此类日志记录的输出将被发送到stderr
,用户还可以获得其他好处,例如指定日志级别

这就是使用此类记录器的方式:

#[macro_use]
extern crate log;
extern crate env_logger;

fn main() {
    env_logger::init().unwrap();
    error!("this is printed by default");
}

(示例改编自)

所以,它是
println\u stderr!(“你好{}!”,名字)
vs.
writeln!(&mut std::stdio::stderr(),“Hello{}!”,name)
,两者的作用几乎相同?它们的作用相同,但宏处理失败案例(返回值)时没有任何瑕疵。如果没有它,您将收到警告。您还可以执行
writeln!(…).unwrap()以最简单的方式处理可能出现的故障。我的答案在夜间没有警告。您看到了什么?此解决方案不起作用:错误:非项语句之后不允许导入。如果在另一个语句之后的块中使用宏,则我会遇到这种情况。如果在另一个块中使用
use
match
来包装内部位,则它对我有效。所以
($($arg:tt)*)=>({use…})
use std::io::Write;

macro_rules! println_stderr(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

fn main() {
    let name = "world";
    println_stderr!("Hello {}!", name)
}
stderr!("Code {}: Danger, Will Robinson!  Danger!", 42);
macro_rules! stderr {
    ($($arg:tt)*) => (
        use std::io::Write;
        match writeln!(&mut ::std::io::stderr(), $($arg)* ) {
            Ok(_) => {},
            Err(x) => panic!("Unable to write to stderr (file handle closed?): {}", x),
        }
    )
}
#[macro_use]
extern crate log;
extern crate env_logger;

fn main() {
    env_logger::init().unwrap();
    error!("this is printed by default");
}