How to print out Python message to linux stdout immediately
You could call flush
on stdout
. If it is possible and practical for you to adjust your code to flush your buffers after the print
call, in test.py
:
from sys import stdout
from time import sleep
def log():
while True:
print('Test log message')
# flush your buffer
stdout.flush()
sleep(1)
While running this logging test, you can check the nohup.txt
file and see the messages being printed out in realtime.
How to read stdout immediately in Python subprocess
An example for you where you read and write to the child several times (as you stated in a comment under the question).
The subprocess (test.py
) will:
- read a line
- convert each one to upper case, and write it back,
- sleep 2 seconds
- repeat until no more input, and then write a final line
The main process (main.py
) will:
- three times:
- write a line of input to the subprocess
- read the answer and say how long it took to get the answer back
- sleep 5 seconds
- at the end, read any final output using
communicate
, and report this
Here is the output of the code that is shown below:
writing to child: hello world 0
child replied with: HELLO WORLD 0
got answer back within 0.00022 seconds
writing to child: hello world 1
child replied with: HELLO WORLD 1
got answer back within 0.00012 seconds
writing to child: hello world 2
child replied with: HELLO WORLD 2
got answer back within 0.00021 seconds
final output from child: finishing
And here is the code:
test.py
import sys
import time
while True:
value = sys.stdin.readline()
if not value:
break
sys.stdout.write(value.upper())
sys.stdout.flush()
time.sleep(2)
sys.stdout.write("finishing\n")
main.py
from subprocess import Popen, PIPE, STDOUT
import time
child = Popen(['python.exe', 'test.py'], stdin=PIPE, stdout=PIPE, stderr=STDOUT)
time.sleep(1)
for i in range(3):
data_in = f"hello world {i}"
print(f"writing to child: {data_in}")
time0 = time.time()
child.stdin.write(f"{data_in}\n".encode())
child.stdin.flush()
data_out = child.stdout.readline()
time1 = time.time()
result = data_out.decode().strip()
elapsed_time = time1 - time0
print(f"child replied with: {result}")
print(f"got answer back within {elapsed_time:.5f} seconds\n")
time.sleep(5)
output, error = child.communicate()
print(f"final output from child: {output.decode()}")
(Tested on Linux using python
instead of python.exe
- hopefully it will work equally on Windows although I can't test this.)
As you can see, the answer is received without having to wait for the sleep
to complete.
(Obviously if the sleep time in the parent is reduced to below about 2 seconds, then the child would not be ready to receive the data when it is sent, so then there would be more of a wait to get an answer back.)
With this sort of two-way communication, it is very easy to end up in a deadlock situation (each process is waiting for the other to do something). To avoid that, each process writes exactly one line each time, ensuring that it ends with a newline, and immediately flushes the output buffer -- and the reading process uses readline()
to read exactly one line (reads until newline). Then hopefully the two should remain in step and avoid deadlocks.
How can I print text immediately without waiting for a newline in Perl?
You need to set autoflush for STDOUT. Example:
use IO::Handle;
STDOUT->autoflush(1);
foreach (1..20) {
print '.';
sleep(1);
}
printf doesn't print a string immediately
The output stream stdout
is buffered by default, so if you want immediate output you'll need to flush the output stream - using fflush
- or cause a newline to be printed in the printf
:
printf("Starting nets allocation...");
fflush(stdout);
Or:
printf("Starting nets allocation...\n");
Note that you can also control buffering at a file pointer level using the setbuf
function from stdio.h:
setbuf(stdout, NULL);
The second argument to setbuf
is a buffer supplied by the caller to be used for buffering output to the stream. Passing NULL indicates that buffering is to be disabled, and is equivalent to:
setvbuf(stdout, NULL, _IONBF, 0);
which also disables buffering on the specified stream.
See docs for setbuf
here.
How to print with end= immediately in Python 3?
You need to flush stdout
:
print("first", end=" ", flush=True)
stdout
is line buffered, which means the buffer is flushed to your screen every time you print a newline. If you are not printing a newline, you need to flush manually.
For anyone not yet using Python 3.3 or newer, the flush
keyword argument is new in 3.3. For earlier versions you can flush stdout
explicitly:
import sys
print("first", end=" ")
sys.stdout.flush()
How can I flush the output of the print function?
In Python 3, print
can take an optional flush
argument:
print("Hello, World!", flush=True)
In Python 2, after calling print
, do:
import sys
sys.stdout.flush()
By default, print
prints to sys.stdout
(see the documentation for more about file objects).
C: printf does not output immediately
Since you use scanf
to wait for user input, it will wait until you give some input to the program.
printf
doesn't put all of the characters to the screen immediately, it buffers it's output. And as long as your program doesn't terminate or you don't call flush(stdout)
to flush the buffer or you don't put newline character \n
at the end of first parameter to printf the output won't be printed to the screen.
change your call to printf
to:
printf("Enter radius\n: ")
use newline so that the string is printed immediately and buffer is flushed
or if you do not want to use newline
printf("Enter radius: ")
fflush(stdout)
call fflush(stdout) to manually flush the output buffers.
Related Topics
Rails 5 Db Migration: How to Fix Activerecord::Concurrentmigrationerror
How to Model a Mutual Friendship in Rails
Missing File in Gem After Build
Save All Image Files from a Website
Ruby on Rails - Doesn't Create Script/Server
Ruby on Rails Source Code Security/Obfuscation
How to Run Code After Each Line in Ruby
Ruby on Rails: How to Add a CSS File with Rails Project
Writing an Activerecord Adapter
How to Reset a Factory_Girl Sequence
Add Existing Classes into a Module
How to Print Stdout Immediately
Undefined Method (Nomethoderror) Ruby
How to Get the Current Test Filename from Rspec
How to Format a Date to Mm/Dd/Yyyy in Ruby