
本文介绍如何使用 Go 的 exec.Command 启动持续运行的 Python 脚本,并通过 StdoutPipe() 和 goroutine 实现实时、非阻塞地读取和打印其 stdout/stderr 输出。
本文介绍如何使用 go 的 `exec.command` 启动持续运行的 python 脚本,并通过 `stdoutpipe()` 和 goroutine 实现实时、非阻塞地读取和打印其 stdout/stderr 输出。
在 Go 中调用外部 Python 脚本并实时处理其输出,关键在于分离进程启动与等待逻辑,并采用流式读取方式——而非使用会阻塞至进程结束的 cmd.Run()。正确做法是:调用 cmd.Start() 异步启动子进程,再通过 cmd.StdoutPipe() 和 cmd.StderrPipe() 获取可读管道,最后用 goroutine 配合 bufio.Scanner 持续扫描并输出每一行。
以下是一个完整、健壮的实现示例:
package main
import (
"bufio"
"fmt"
"io"
"log"
"os/exec"
)
func main() {
cmd := exec.Command("python", "game.py")
// 获取 stdout 和 stderr 的读取管道
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Fatal("获取 stdout 管道失败:", err)
}
stderr, err := cmd.StderrPipe()
if err != nil {
log.Fatal("获取 stderr 管道失败:", err)
}
// 启动子进程(不等待退出)
if err := cmd.Start(); err != nil {
log.Fatal("启动 Python 进程失败:", err)
}
// 并发读取 stdout 和 stderr
go func() {
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
fmt.Printf("[OUT] %s\n", scanner.Text())
}
if err := scanner.Err(); err != nil && err != io.EOF {
log.Printf("读取 stdout 时出错: %v", err)
}
}()
go func() {
scanner := bufio.NewScanner(stderr)
for scanner.Scan() {
fmt.Printf("[ERR] %s\n", scanner.Text())
}
if err := scanner.Err(); err != nil && err != io.EOF {
log.Printf("读取 stderr 时出错: %v", err)
}
}()
// 主 goroutine 等待子进程终止(如需优雅退出可配合 context)
if err := cmd.Wait(); err != nil {
log.Printf("Python 进程异常退出: %v", err)
}
}
⚠️ 重要注意事项:
-
Python 输出缓冲问题:默认情况下,
print在非 TTY 环境(如被 Go 进程管道捕获时)会启用行缓冲或全缓冲,导致输出延迟甚至卡住。务必在 Python 脚本中显式刷新标准输出:import sys print("Hello") sys.stdout.flush() # 必须添加!或更简洁地使用
print(..., flush=True)(Python 3.3+):print("Hello", flush=True) 错误处理增强:示例中对
StdoutPipe/StderrPipe和cmd.Start()均做了 panic 处理;生产环境建议使用log或自定义错误回调,避免进程意外崩溃。资源安全:
cmd.Wait()必须在所有管道读取 goroutine 完成后调用,否则可能提前关闭管道引发io.ErrClosed。当前结构已确保 goroutine 启动后才等待,符合安全模型。扩展建议:如需支持超时控制、信号中断(如
Ctrl+C终止子进程)、或结构化日志(如带时间戳、进程 ID 标识),可进一步结合context.WithTimeout、cmd.Process.Signal()及log.SetPrefix等机制实现。
掌握这一模式后,你不仅能处理 Python 脚本,还可无缝迁移到 Node.js、Rust CLI 工具等任意长期输出型外部命令的集成场景。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











