news 2026/9/17 20:58:50

用 Unix 管道打通 Rerun:stdio 示例详解——SDK 写标准输出、Viewer 读标准输入

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用 Unix 管道打通 Rerun:stdio 示例详解——SDK 写标准输出、Viewer 读标准输入

用 Unix 管道打通 Rerun:stdio 示例详解——SDK 写标准输出、Viewer 读标准输入

【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun

examples/python/stdio是 Rerun 仓库中一个短小精悍的示例:它演示了如何使用 Rerun SDK 将日志数据写到标准输出(stdout),再通过管道交给 Rerun Viewer 从标准输入(stdin)读取并可视化。读完本文,你将掌握一条可复用的"记录 → 传输 → 可视化"管道范式:任何能产生 RRD 数据流的程序都可以像 Unix 工具一样与rerun -组合,从而把可视化无缝嵌入已有的 shell 管线。

示例的核心:一条管道命令

该示例的 README 用一句话点明了全部主题:Demonstrates how to log data to standard output with the Rerun SDK, and then visualize it from standard input with the Rerun Viewer(演示如何用 Rerun SDK 将数据记录到标准输出,再用 Rerun Viewer 从标准输入进行可视化)。配套的可运行命令只有一行:

echo 'hello from stdin!' | python stdio.py | rerun -

这条命令由三段构成,恰好对应"生产数据 → 记录数据 → 消费数据"的完整链路:

  1. echo 'hello from stdin!':模拟任何向标准输入写入内容的来源;
  2. python stdio.py:Rerun SDK 程序,读取自身 stdin 的文本,再以 RRD 编码格式写到自己的 stdout;
  3. rerun -:Rerun Viewer 的命令行入口,其中-表示"从标准输入读取数据",代替常规的文件路径参数。

数据以二进制 RRD 流的形式在管道中传递,最终在 Viewer 中呈现为一个文本日志实体。

Python 实现逐步解析

示例的 Python 源码位于 examples/python/stdio/stdio.py,全文仅 22 行,注释清晰,是理解该模式的最佳入口:

#!/usr/bin/env python3 """ Demonstrates how to use standard input/output with the Rerun SDK/Viewer. Usage: `echo 'hello from stdin!' | python main.py | rerun -` """ from __future__ import annotations import sys import rerun as rr # pip install rerun-sdk # sanity-check since all other example scripts take arguments: assert len(sys.argv) == 1, f"{sys.argv[0]} does not take any arguments" rr.init("rerun_example_stdio") rr.stdout() input = sys.stdin.buffer.read() rr.log("stdin", rr.TextDocument(input.decode("utf-8")))

逐步拆解其关键动作:

  • rr.init("rerun_example_stdio"):以固定的 application id 初始化 Rerun SDK。该 id 用于标识这条记录流,Viewer 中也会据此组织实体树与蓝图;
  • rr.stdout():这是本示例的灵魂调用。它把后续所有rr.log产生的数据输出到标准输出,而不是默认的"spawn 一个 Viewer 进程"。注意 SDK 文档要求在 log 任何数据之前调用(Call thisbeforeyou log any data!);
  • sys.stdin.buffer.read():以二进制模式读取标准输入的全部内容。示例刻意保持简单,把整个输入当作一个整体处理;
  • rr.log("stdin", rr.TextDocument(input.decode("utf-8"))):在实体路径stdin下记录一个TextDocument(文本文档)组件。解码后文本会在 Viewer 中以富文本形式展示。

工程化入口:pyproject.toml

该示例还提供了可安装的脚本入口,见 examples/python/stdio/pyproject.toml:

[project] name = "stdio" version = "0.1.0" readme = "README.md" dependencies = ["rerun-sdk"] [project.scripts] stdio = "stdio:main" [build-system] requires = ["hatchling"] build-backend = "hatchling.build"

依赖仅有rerun-sdk一项;[project.scripts]定义了stdio命令,等价于"安装后直接以stdio命令运行stdio.py"。如果不想安装,直接用python stdio.py运行也可以,命令中的python stdio.py与 README 中的用法完全一致。

Rust 与 C++ 的同主题实现

stdio 模式并非 Python 独有,仓库中提供了三语言对照实现,这有助于理解其通用性。

Rust 版本

examples/rust/stdio/src/main.rs 使用RecordingStreamBuilder完成同样的工作:

//! Usage: //! ```text //! echo 'hello from stdin!' | cargo run | rerun - //! ``` use itertools::Itertools as _; fn main() -> Result<(), Box<dyn std::error::Error>> { let rec = rerun::RecordingStreamBuilder::new("rerun_example_stdio").stdout()?; let lines: Vec<String> = std::io::stdin().lines().try_collect()?; let input = lines.join("\n"); rec.log("stdin", &rerun::TextDocument::new(input))?; Ok(()) }

对应关系一目了然:RecordingStreamBuilder::new("rerun_example_stdio").stdout()?等价于 Python 的rr.init(...)+rr.stdout()rec.log("stdin", &rerun::TextDocument::new(input))等价于 Python 的rr.log("stdin", rr.TextDocument(...))。运行命令同样是echo 'hello from stdin!' | cargo run | rerun -

C++ 版本

examples/cpp/stdio/main.cpp 则通过rerun::RecordingStreamto_stdout()完成接线:

#include <iostream> #include <string> #include <rerun.hpp> int main() { const auto rec = rerun::RecordingStream("rerun_example_stdio"); rec.to_stdout().exit_on_failure(); std::string input; std::string line; while (std::getline(std::cin, line)) { input += line + '\n'; } rec.log("stdin", rerun::TextDocument(input)); }

其中to_stdout().exit_on_failure()不仅把输出切换到 stdout,还会在出错时直接终止程序,避免静默失败。编译运行方式见 examples/cpp/stdio/README.md:

cmake . cmake --build . --target example_stdio echo 'hello from stdin!' | ./examples/cpp/stdio/example_stdio | rerun -

三个版本结构完全同构,说明"SDK 写 stdout、Viewer 读 stdin"是 Rerun 跨语言的一致能力。

SDK 底层原理:stdout() 输出端是怎么工作的

示例之所以能跑通,关键在于 SDK 的stdout()实现做了精心的设计。以 Rust 为例,源码位于 crates/top/re_sdk/src/recording_stream.rs:

/// Creates a new [`RecordingStream`] that is pre-configured to stream the data through to stdout. /// /// If there isn't any listener at the other end of the pipe, the [`RecordingStream`] will /// default back to `buffered` mode, in order not to break the user's terminal. #[cfg(not(target_arch = "wasm32"))] pub fn stdout(self) -> RecordingStreamResult<RecordingStream> { if std::io::stdout().is_terminal() { re_log::debug!("Ignored call to stdout() because stdout is a terminal"); return self.buffered(); } self.create_recording_stream("stdout", || Ok(Box::new(crate::sink::FileSink::stdout()?))) }

这里有两个值得注意的实现细节:

  • 终端检测与安全回退:如果检测到 stdout 连接的是终端(is_terminal()为真),说明用户直接运行程序而没有接管道,此时会自动回退到buffered模式。这是为了防止把二进制 RRD 数据直接倾倒进用户的终端把屏幕弄花。也就是说,只有在管道另一端确实存在监听者(例如rerun -)时,SDK 才会真正把数据写向 stdout。Python 侧 rerun_py/rerun_sdk/rerun/sinks.py 的stdout()也保留了同样的语义("If there isn't any listener at the other end of the pipe...default back to buffered mode")。
  • 底层是 FileSinkstdout()最终复用了crate::sink::FileSink,即把 stdout 当作一个"文件"来写入 RRD 字节流,与 crates/top/re_sdk/src/recording_stream.rs 中的save()(写.rrd文件)共用同一套文件落盘/流式写入逻辑,只是目标从文件描述符换成了标准输出。

Python 侧的完整签名还提供了额外的控制参数,见 rerun_py/rerun_sdk/rerun/recording_stream.py:

def stdout( self, default_blueprint: BlueprintLike | None = None, *, write_footer: bool = True, ) -> None:
  • default_blueprint:可为该应用指定一个默认蓝图;若应用已有活动蓝图,新蓝图不会自动激活,需要用户在 Viewer 中点击"reset blueprint";
  • write_footer:默认True,控制是否在流末尾写出完整的 RRD footer(包含每个 chunk 的 manifest)。关闭 footer 会显著损害随机访问性能,某些工具(如 LazyStore)可能无法正常工作,因此除非明确知道后果,一般保持默认即可。

Viewer 端:rerun - 如何从标准输入读取

管道下游的rerun -是 CLI 层面的标准输入约定。在 Rerun CLI 的命令解析模块 crates/top/rerun/src/commands/entrypoint.rs 中,"-"与普通文件路径、URL 一样被当作合法的输入源处理(例如在参数校验测试assets_require_a_local_recording中,"-"被列为一种 source 类型)。

进一步地,Rerun 将"从文件或 stdin 读取 RRD 流"抽象成了可复用的能力:read_rrd_streams_from_file_or_stdinread_raw_rrd_streams_from_file_or_stdin在 crates/top/rerun/src/commands/mod.rs 中统一导出,并被rerun rrd filter(见 crates/top/rerun/src/commands/rrd/filter.rs)等子命令复用。这意味着"从标准输入读 RRD"不只在 viewer 打开场景生效,还贯穿于整个rerun rrd工具链——例如可以把一个管道中的 RRD 流直接交给rerun rrd filter做过滤,再接上 Viewer。

实际使用场景与注意事项

基于以上原理,stdio 模式适合以下场景:

  • 嵌入 shell 管线:把可视化当作 Unix 过滤器使用,与其他命令(grepjqawk等)自由组合,实现"边处理边看";
  • 进程间传递记录流:一个长期运行的采集进程把 RRD 写到 stdout,另一个进程或rerun -负责消费,进程间通过管道解耦;
  • 配合rerun rrd子命令:对管道的 RRD 流做再加工(如 filter/merge)后再可视化。

使用中需要特别注意:

  1. stdout 上只能有 RRD 数据:既然 stdout 承载了二进制记录流,就不要再向 stdout 打印print()调试信息——这会污染管道、导致 Viewer 解析失败。调试日志应走 stderr 或日志系统(Rerun 的日志走 stderr 不影响管道);
  2. stdin 同样被占用:示例程序读取了自身 stdin 的全部内容,因此这个模式天然适合"一次性处理"的过滤器语义,而非交互式程序;
  3. 无监听者时的回退:如果直接运行 SDK 程序而不接管道,数据不会丢失,但会进入 buffered 模式(Python 端同样如此),这一点由 SDK 自动处理,无需用户干预;
  4. 管道是瞬时的:stdout 流不像 gRPC 或文件那样支持 Viewer 中途连接/回放历史数据,管道生命周期由两侧进程共同决定。

继续深入

  • 示例源码:examples/python/stdio/stdio.py、examples/rust/stdio/src/main.rs、examples/cpp/stdio/main.cpp
  • SDK stdout 实现:crates/top/re_sdk/src/recording_stream.rs、rerun_py/rerun_sdk/rerun/sinks.py
  • Viewer/CLI 的 stdin 输入源:crates/top/rerun/src/commands/entrypoint.rs、crates/top/rerun/src/commands/mod.rs

【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 20:58:34

X6 开发者工具使用指南:借助 DevTools 审查与调试图实例

X6 开发者工具使用指南&#xff1a;借助 DevTools 审查与调试图实例 【免费下载链接】X6 &#x1f680; JavaScript diagramming library that uses SVG and HTML for rendering. 项目地址: https://gitcode.com/GitHub_Trending/x6/X6 X6 是基于 HTML 和 SVG 的图编辑引…

作者头像 李华
网站建设 2026/9/17 20:55:49

微信小程序全流程开发实战:从注册到上线与跨端通信

微信小程序开发这事&#xff0c;看着门槛不高&#xff0c;但真要完整走一遍平台开发流程&#xff0c;从注册账号、搭环境、写页面、调接口&#xff0c;到最终过审上线&#xff0c;中间可踩的坑一点都不少。尤其是最近大家问得多的&#xff0c;什么“hbuilderx发行微信小程序超详…

作者头像 李华
网站建设 2026/9/17 20:53:07

非正式市场价格信号扭曲的根源与矫正方法

1. 市场信号扭曲的根源与矫正逻辑在当代社会经济运行中&#xff0c;存在着大量被主流经济学忽视的"非正式市场"——那些不受正式制度保护却真实影响人们生活的交易场域。这些市场的价格信号往往严重偏离其本质功能&#xff0c;形成了独特的价值扭曲现象。作为一名长期…

作者头像 李华
网站建设 2026/9/17 20:51:23

GJB 3206A技术状态管理:标识、基线、更改与审核落地

简介&#xff1a;配置管理与产品数据管理的核心&#xff0c;是让设计、制造、交付各环节对“当前有效版本”有唯一、可追溯的定义。其原理是通过标识、基线、更改控制和记实审核&#xff0c;把产品功能与物理特性固化到受控文件中&#xff0c;并在变更时维持文实一致。技术价值…

作者头像 李华