Go无法实时捕获Python子进程STDOUT,STDERR正常输出问题求助
问题:Go捕获子进程stdout无法实时输出,stderr正常
我写了一个简单的Python脚本,每秒生成两条stdout/stderr消息:
#!/usr/bin/env python3 import sys, time for a in range(10): if(a%2==0): print(a, file=sys.stdout) else: print(a, file=sys.stderr) time.sleep(0.5) print("This is an STDOUT message") print("This is an STDERR message", file=sys.stderr) sys.exit(1)
该脚本的示例输出:
> ./runstatus.py 0 <- STDOUT, after 0.5s 1 <- STDERR, after 0.5s 2 <- STDOUT, after 0.5s 3 ... 4 5 6 7 8 9 This is an STDOUT message <- STDOUT This is an STDERR message <- STDERR
我需要用Go语言实时捕获该子进程的stdout和stderr输出,于是编写了如下Go代码:
package main import("bufio"; "fmt"; "os/exec") func readerr(scanner *bufio.Scanner, channel string) { for scanner.Scan() { fmt.Println(channel, scanner.Text()); } } func main() { cmd:=exec.Command("./runstatus.py") stdout, _:=cmd.StdoutPipe() stderr, _:=cmd.StderrPipe() scanout:=bufio.NewScanner(stdout) scanerr:=bufio.NewScanner(stderr) scanout.Split(bufio.ScanLines) scanerr.Split(bufio.ScanLines) go readerr(scanout, "out:") go readerr(scanerr, "err:") cmd.Start() cmd.Wait() }
但实际运行时,只有STDERR能实时输出,STDOUT会在进程执行结束时一次性全部输出,具体输出如下:
err: 1 <- STDERR, after 1s err: 3 <- STDERR, after 1s err: 5 err: 7 err: 9 out: 0 <- STDOUT, after 5s, from here, the rest just flushes abruptly! out: 2 out: 4 out: 6 out: 8 out: This is an STDOUT message err: This is an STDERR message
请问哪里操作出错了?
解决方案
这不是Go代码的问题,而是Python的标准输出缓冲机制导致的:
- Python默认会对stdout进行行缓冲或块缓冲,当stdout不是终端(比如被Go程序通过管道捕获)时,会启用块缓冲,直到缓冲区满或者进程结束才会一次性输出。
- 而stderr默认是无缓冲的,所以能实时输出内容。
解决方法有两种:
方法1:修改Python脚本,强制刷新stdout
每次print后手动调用sys.stdout.flush(),或者在print时加上flush=True参数:
#!/usr/bin/env python3 import sys, time for a in range(10): if(a%2==0): print(a, file=sys.stdout, flush=True) # 加上flush=True else: print(a, file=sys.stderr) time.sleep(0.5) print("This is an STDOUT message", flush=True) print("This is an STDERR message", file=sys.stderr) sys.exit(1)
方法2:在启动Python进程时禁用缓冲
在Go中启动Python命令时,加上-u参数(该参数会强制Python不缓冲stdout和stderr):
cmd:=exec.Command("python3", "-u", "./runstatus.py")
这样不需要修改Python脚本,也能让stdout实时输出。
内容的提问来源于stack exchange,提问作者RodolfoAP
相关产品推荐
相关产品推荐

