Trying to understand the Flush argument behavior in print python - python

Python print flush:
from time import sleep
print("Hello, world!", end='')
sleep(5)
print("Bye!!!")
Ideally, in this scenario, Hello world! and Bye!! should be printed together as flush is defaulted to False. But when I am running this, it is print Hello world! and then after 5 seconds, printing Bye!!.
and I have tried the flush=False and flush=True one by one. But these also behaving exactly same
can any one please help me in finding a way to observe the behavior of flush, practically?

Related

Why does the same code works differently?

Well, I have read that stdout is line-buffered. But the code works differently in Pydroid 3(unaware of the exact version) and Python 3.8.3.
import time
print('Hello', end = '')
time.sleep(5)
print('World')
In Pydroid 3, both Hello and World are printed after (at least after) 5 seconds while in Python 3.8.3, Hello is printed first, and World is printed after 5 seconds.
Why is the code working differently?
It is probably not a Python version issue, but a different terminal issue.
Some terminals (or more accurately files/streams, stdout included) only flush after a newline (which the first print doesn't have), while others can flush after every write.
to force a flush you can use flush=True as a param to print, try this:
import time
print('Hello', end='', flush=True)
time.sleep(5)
print('World')

Why print in Python doesn't pause when using sleep in a loop?

This code:
import time
for i in range(10):
print(i)
time.sleep(.5)
Causes my computer to hang for 5 seconds, and then print out 0-9, as opposed to printing a digit every half second. Am I doing something wrong?
print, by default, prints to sys.stdout and that buffers the output to be printed, internally.
Whether output is buffered is usually determined by file, but if the flush keyword argument is true, the stream is forcibly flushed.
Changed in version 3.3: Added the flush keyword argument.
Quoting sys.stdout's documentation,
When interactive, standard streams are line-buffered. Otherwise, they are block-buffered like regular text files.
So, in your case, you need to explicitly flush, like this
import time
for i in range(10):
print(i, flush=True)
time.sleep(.5)
Okay, there is a lot of confusion around this buffering. Let me explain as much as possible.
First of all, if you are trying this program in a terminal, they do line buffering (which basically means, whenever you encounter a newline character, send the buffered data to stdout), by default. So, you can reproduce this problem in Python 2.7, like this
>>> import time
>>> for i in range(10):
... print i,
... time.sleep(.5)
...
And in Python 3.x,
>>> for i in range(10):
... print(i, end='')
... time.sleep(.5)
We pass end='' because, the default end value is \n, as per the print's documentation,
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
Since the default end breaks the line buffering, the data will be sent to stdout immediately.
Another way to reproduce this problem is to store the actual program given by OP in a file and execute with Python 3.x interpreter, you will see that the stdout internally buffers the data and waits till the program finishes to print.
Try this:
for i in range(10):
sys.stdout.write('\r' + str(i))
time.sleep(.5)
here '/r' is carriage return, it brings the cursor first place again.

python - raw_input and thread [duplicate]

I'm trying to let the user input commands at a console using raw_input(), this works fine. The problem is I have background threads that occasionally output log-information to the screen and when they do they mess up the input prompt (since the output go wherever the cursor happens to be at the moment).
This is a small Python program that illustrate what i mean.
#!/usr/bin/env python
import threading
import time
def message_loop():
while True:
time.sleep(1)
print "Hello World"
thread = threading.Thread(target = message_loop)
thread.start()
while True:
input = raw_input("Prompt> ")
print "You typed", input
This is an example of what it could look like when I run it:
Prompt> Hello World
Hello World
Hello World
Hello World
test
You typed test
Prompt> Hello World
Hello World
Hello World
hellHello World
o
You typed hello
Prompt> Hello World
Hello World
Hello World
Hello World
What I want is for the prompt to move along with the output from the thread. Like so:
Hello World
Hello World
Prompt> test
You typed test
Hello World
Hello World
Hello World
Hello World
Hello World
Prompt> hello
You typed hello
Hello World
Hello World
Hello World
Hello World
Prompt>
Any ideas on how to achieve this without resorting to ugly hacks? :)
I recently encountered this problem, and would like to leave this solution here for future reference.
These solutions clear the pending raw_input (readline) text from the terminal, print the new text, then reprint to the terminal what was in the raw_input buffer.
This first program is pretty simple, but only works correctly when there is only 1 line of text waiting for raw_input:
#!/usr/bin/python
import time,readline,thread,sys
def noisy_thread():
while True:
time.sleep(3)
sys.stdout.write('\r'+' '*(len(readline.get_line_buffer())+2)+'\r')
print 'Interrupting text!'
sys.stdout.write('> ' + readline.get_line_buffer())
sys.stdout.flush()
thread.start_new_thread(noisy_thread, ())
while True:
s = raw_input('> ')
Output:
$ ./threads_input.py
Interrupting text!
Interrupting text!
Interrupting text!
> WELL, PRINCE, Genoa and Lucca are now no more than private estates of the Bo
Interrupting text!
> WELL, PRINCE, Genoa and Lucca are now no more than private estates of the Bo
naparte family. No, I warn you, that if you do not tell me we are at war,
The second correctly handles 2 or more buffered lines, but has more (standard) module dependencies and requires a wee bit of terminal hackery:
#!/usr/bin/python
import time,readline,thread
import sys,struct,fcntl,termios
def blank_current_readline():
# Next line said to be reasonably portable for various Unixes
(rows,cols) = struct.unpack('hh', fcntl.ioctl(sys.stdout, termios.TIOCGWINSZ,'1234'))
text_len = len(readline.get_line_buffer())+2
# ANSI escape sequences (All VT100 except ESC[0G)
sys.stdout.write('\x1b[2K') # Clear current line
sys.stdout.write('\x1b[1A\x1b[2K'*(text_len/cols)) # Move cursor up and clear line
sys.stdout.write('\x1b[0G') # Move to start of line
def noisy_thread():
while True:
time.sleep(3)
blank_current_readline()
print 'Interrupting text!'
sys.stdout.write('> ' + readline.get_line_buffer())
sys.stdout.flush() # Needed or text doesn't show until a key is pressed
if __name__ == '__main__':
thread.start_new_thread(noisy_thread, ())
while True:
s = raw_input('> ')
Output. Previous readline lines cleared properly:
$ ./threads_input2.py
Interrupting text!
Interrupting text!
Interrupting text!
Interrupting text!
> WELL, PRINCE, Genoa and Lucca are now no more than private estates of the Bo
naparte family. No, I warn you, that if you do not tell me we are at war,
Useful sources:
How to get Linux console window width in Python
apt like column output - python library
(This code sample shows how to get terminal width for either Unix or Windows)
http://en.wikipedia.org/wiki/ANSI_escape_code
I think you need something that lets you dynamically print/delete/overwrite text from the terminal window e.g. how the UNIX watch or top commands work.
I think in your case you would print "Prompt>" but then when you get a "Hello World" you overwrite "Prompt>" with "Hello World", and then print "Prompt>" on the line below. I don't think you can do that with regular output printing to the terminal.
You might be able to do what you want using Python's curses library. I have never used it so I can't tell you how to solve your problem (or if the module will even be able to solve your problem), but I think it is worth taking a look into. A search for "python curses tutorial" provided a PDF tutorial document which seems helpful.
you need to update stdout from a single thread, not from multiple threads... or else you have no control over interleaved i/o.
you will want to create a single thread for output writing.
you can use a Queue in the thread and have all other threads write their output logging info to it.. then read from this Queue and write to stdout at appropriate times along with your prompt message.
I don't think it's possible. How should that behave anyways? Nothing shows up until the user presses Enter? If that's so, output would only come when the user issues a command (or whatever your system expects), and that doesn't sound desirable.
Methinks your threads should output to another file.

Print on the same line, step after step

I've developed a Python script that performs several tasks in a row (mainly connecting to servers and retrieving information).
There are many steps, and for each of them I would like to display a dot, so that the user knows there is something going on.
At the end of each step, I do:
print('.', end='')
And in the final step, I write:
print('Done!')
It works, except nothing is displayed until the final print is executed, so it kind of defeats its original purpose :)
Basically, nothing is displayed on the screen, and at the very last moment, this pops up:
.......Done!
How can I force Python to print on the same line step after step?
By default, stdout is line buffered, meaning the buffer won't be flushed until you write a newline.
Flush the buffer explicitly each time you print a '.':
print('.', end='', flush=True)
The flush keyword was added in Python 3.3; for older versions, use sys.stdout.flush().
From the print() function documentation:
Whether output is buffered is usually determined by file, but if the flush keyword argument is true, the stream is forcibly flushed.
and from the sys.stdout documentation (the default value for the file argument of the print() function):
When interactive, standard streams are line-buffered. Otherwise, they are block-buffered like regular text files.
Instead of using print, you can write directly to stdout, (unbuffered):
import sys
import time
for i in range (10):
time.sleep (0.5)
sys.stdout.write('.')
print 'Done!'
for python 2.7.3 you can left a trailing comma which tells the idle to not insert a line after the statement is printed for example
print "hello",
print "world"
would return
>>> hello world

print statements only appearing before or after a subprocess call

This question is related to Python: why print statements and subprocess.call() output are out of sync? but the solutions are not working for my particular situation. I am trying to accomplish an automation test process in python that has first prints the name of a Test Suite, then has a for loop which iterate through a list printing the name of a particular test, followed by a subprocess call to execute the test, ended with a print statement that the test is finished. Lastly, I print a statement that says it is the end of the test suite name.
i.e.
=========BEGIN TEST SUITE: =========
---------start test: ----------
subprocess call to execute test
---------end test: ------------
repeat for tests
=========END TEST SUITE: ==========
My current code works fine but when I redirect its output to a file, it puts all the print statements at the bottom. When using the solutions in the other question, it does the complete opposite for me and prints all the print statements first, then executes the test. I tried used the sys.stdout.flush(), as well as turning off the buffering but both give me the same thing. How can I get everything to be printed exactly the way it executes/is in the code when I redirect output or write to a file??
The way I generally solve problems like this is to capture the output in the python program and print it when I want it to print using a Popen
>>> def do_ls():
... print "I'm about to ls"
... ls = subprocess.Popen('ls', stdout=subprocess.PIPE)
... output = ls.communicate()[0] #wait for the process to finish, capture stdout
... print 'ls output:'
... print output
... print 'done.'
I can show you how to do this more specifically for your tests if you post some code

Categories

Resources