Given the following small program:
#!/usr/bin/env python3
import time
for i in range(15):
print(f'{i}: sleeping')
time.sleep(1)
When I run it with stdout
attached to the terminal directly, I get the output pretty much immediately:
./sync_test.py
However, if I run my program with stdout
attached to a pipe (which on the other end cat
is listening and printing to the terminal), I don't get the output until the program ends:
./sync_test.py | cat
The only way I can get the output to be printed before the program quits is if I add flush=True
to all of my print statements.
I tried this out in a few other languages (Go, Java, and C) and got mixed results. In Go and Java, the programs print immediately when stdout
is not attached to a TTY. But with C, I experience the same behavior as I do with Python.
The Go program (test_go.go):
package main
import (
"fmt"
"time"
)
func main() {
for i := 0; i < 15; i++ {
fmt.Printf("%d: sleeping\n", i)
time.Sleep(1 * time.Second)
}
}
The Java program (test_java.java):
public class test_java {
public static void main(String[] args) throws Exception{
for(int i=0; i<15; i++){
System.out.println(i + ": sleeping");
Thread.sleep(1000);
}
}
}
The C program (test_c.c):
#include <stdio.h>
#include <unistd.h>
int main() {
for(int i=0; i < 15; i ++) {
printf("Hello, World!\n");
sleep(1);
}
return 0;
}
(all programs were run with | cat
at the end of the command)
I understand that stdout
is buffered. What is the explanation for the differences in behavior across languages? And whether stdout
is connected to a TTY or not? Are Java and Go flushing the buffers implicitly whereas C and Python are not?