Home > database >  Can't capture cmd.Run() stdout, stderr is fine
Can't capture cmd.Run() stdout, stderr is fine

Time:10-24

This simple python script generates stdout/stderr messages, two per second.

#!/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)

Example output:

> ./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

I need to capture the stdout and stderr outputs in realtime with golang, so I found moreover this:

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()
}

But the problem is this just works with STDERR!!! Stderr goes in realtime, but stdout not, it bumps suddenly at the end of the execution:

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

What am I doing wrong?

CodePudding user response:

Probably the problem is that in Python the print output to stdout is buffered. The solution may depend on the Python version.

For example, run a script with the -u option

python -u ./runstatus.py

Since Python 3.3, the print function has a flash parameter, you can try using it:

print(a, file=sys.stdout, flush=True)
  • Related