Printing multiple lines of output with the CMD shell (Python) - python

I have a simple question today. Basically, I want to print 2 or more lines of output in the CMD shell with python. Here is an example:
Regular CMD Shell:
Output
What I want:
Output
Output1
Ect.
I'm using Python 3.x fyi. I don't even know if this is possible with typical Python libraries, thanks for your answers!
Edit: Due to confusion, I've dedcided to write more in detail. I'd like to have 2 or more live outputs while a loop or something of the matter is running. So, for example, if I was running a clock in a while True loop, I could use the carriage return function and have 2 outputs running.
Edit #2: So I'm going to give you guys a situation in which I would need an answer to this question. Basically, I made a loop that displays the current time and the time until 7:30 pm to the CMD shell using a return so it all stays neatly on one line. However, I need it so instead of me printing all the information I need on 1 line, it does it on 2. Here is the output:
Time: 12:44:38 Time Left Until 7:30: 6:45:22
What I want it to be:
Time: 12:44:38
Time Left Until 7:30: 6:45:22
Here is my code:
import datetime
import time
import sys
while True:
start_time = datetime.datetime.now().time().strftime('%H:%M:%S')
end_time = ('19:30:00')
total_time=(datetime.datetime.strptime(end_time,'%H:%M:%S') - datetime.datetime.strptime(start_time,'%H:%M:%S'))
print ('Time: ', start_time, 'Time Left Until 7:30: ', total_time, end='\r')
time.sleep(0.1)
When I try to print anything below the carriage return, it doesn't print and when I put the carriage return in the second print, the original loop prints down and not in one line. Thanks again!

If cls command blinks, you can use ANSI commands to control. First you have to enable ANSI in the windows cmd. You can use a 3rd party library such as colorama to do that.
Once you've enabled ANSI, you can use it to move up a line and delete a line (and also add nice colors 😉).
colorama.init() # don't forget to call
Up a line: sys.stout.write('\033[1A')
Delete current line: sys.stout.write(' \r\033[K')

You can refresh the cmd window by calling os.system('cls'). This will clear the screen and allow you to print your updated output.

Related

What does this mean in Python '\x1b[2K'?

I've just learnt that to clear a line that you printed in Python, do this:
sys.stdout.write('\x1b[2K')
Why is it so complicated? what does that weird code mean? and is there any alternative in print command?
Print does offer "end" option that allows to go back and forth in lines, but no way to clear what you printed. Overwriting via \r doesn't always work especially if the new line is shorter than the old one. You will get traces from the old line, so I need clearing first.
Thanks.
\x1b[2K is what's known as an ANSI terminal control sequence. They are a legacy of the 1970s and still used today (but vastly extended) to control terminal emulators.
\x1b is the ASCII for ESCAPE (literally the ESC key on your keyboard). [2K is the command "erase the current line".
There are many libraries in Python for working with the terminal, such as Urwid. These libraries will hide the inner workings of the terminal from you and give you higher-level constructs to create TUIs.
However, there is a much more efficient way of doing this:
You can use the print() command as usual, and delete the screen using
os.system("cls") # For Windows
or
os.system("clear") # For Linux
Alternative to print on a single line
I have a script that prints the x, y coordinates of the mouse as such:
import pyautogui
import time
while True:
x, y = pyautogui.position()
position_string = "X: {} Y: {}".format(str(x).rjust(4), str(y).rjust(4))
print(position_string, end='')
print('\b' * len(position_string), end='', flush=True)
time.sleep(1)
Where I will point out that you can print the backspace character ('\b') the amount of times that there are characters on the screen (len(position_string)), and when used with the end='' and flush=True options this will constantly print on a single line within your console. I should also note that this does not work in IDLE, but only on an actual command line! In IDLE the backspace characters are actually printed as some weird square shape...
This is called ANSI escape code . 2K is the name for Erase in Line. Quote from the link:
Erases part of the line. If n is 0 (or missing), clear from cursor to the end of the line. If n is 1, clear from cursor to beginning of the line. If n is 2, clear entire line. Cursor position does not change.
You can also try echo -e '\x1b[2k' in the terminal for better understanding.

Python carriage return not working

I have a long-running script that loops over rows in a database. Every so often I'd like it to print how many rows it's processed, but without creating a new line each time. This is essentially what I have:
import sys
mystr = "{} rows complete\r"
for i in range(0, 100):
if i % 10 == 0:
sys.stdout.write(mystr.format(i))
sys.stdout.flush()
When I run this (on Python 2.7.5 64-bit, Windows) I get:
0 rows complete
10 rows complete
20 rows complete
...
100 rows complete
Can anyone think of why the carriage return isn't working? I've seen some similar questions here about Python and \r, but all the answers say to include sys.stdout.flush(), which I have.
Using \r is probably the correct way to go here, but the behaviour depends very much on how the text is being output. Not all terminals will respect a bare carriage return:
cmd.exe and powershell.exe should both output the text the way you expect (Powershell ISE doesn't but that's a red herring here).
Python's own idle will ignore the carriage return, all output comes on one long line.
As you noted, your own editor's command window also ignores \r.
Also, if you try from an interactive window you also get some numbers output at the end of each line: that's because the interactive windows helpfully outputs the result of the call to sys.stdout.flush().

How can I use \r to make Python print on the same line?

Can someone please thoroughly explain how a '\r' works in Python?
Why isn't the following code printing out anything on the screen?
#!/usr/bin/python
from time import sleep
for x in range(10000):
print "%d\r" % x,
sleep(1)
Your output is being buffered, so it doesn't show up immediately. By the time it does, it's being clobbered by the shell or interpreter prompt.
Solve this by flushing each time you print:
#!/usr/bin/python
from time import sleep
import sys
for x in range(10000):
print "%d\r" % x,
sys.stdout.flush()
sleep(1)
'\r' is just a another ASCII code character. By definition it is a CR or carriage return. It's the terminal or console being used that will determine how to interpret it. Windows and DOS systems usually expect every line to end in CR/LF ('\r\n') while Linux systems are usually just LF ('\n'), classic Mac was just CR ('\r'); but even on these individual systems you can usually tell your terminal emulator how to interpret CR and LF characters.
Historically (as a typewriter worked), LF bumped the cursor to the next line and CR brought it back to the first column.
To answer the question about why nothing is printing: remove the comma at the end of your print line.
Do this instead:
print "\r%d" % x,
This has nothing to do with \r. The problem is the trailing , in your print statement. It's trying to print the last value on the line, and the , is creating a tuple where the last value is empty. Lose the , and it'll work as intended.
Edit:
I'm not sure it's actually correct to say that it's creating a tuple, but either way that's the source of your problem.

How can I edit a string that was printed to stdout?

How can I edit a string that I just printed? For example, for a countdown counter (First prints 30, then changes it to 29 and so on)
Thanks.
Print a carriage return \r and it will take the cursor back to the beginning on the line. Ensure you don't print a newline \n at the end, because you can't backtrack lines. This means you have have to do something like:
import time
import sys
sys.stdout.write('29 seconds remaining')
time.sleep(1)
sys.stdout.write('\r28 seconds remaining')
(As opposed to using print, which does add a newline to the end of what it writes to stdout.)
If you're targeting Unix/Linux then "curses" makes writing console programs really easy. It handles color, cursor positioning etc. Check out the python wrapper:
http://docs.python.org/library/curses.html
If you're on a xterm-like output device, the way you do this is by OVERWRITING the output. You have to ensure that when you write the number you end with a carriage-return (without a newline), which moves the cursor back to the start of the line without advancing to the next line. The next output you write will replace the current displayed number.
You can not change what you printed. What's printed is printed. But, like bradley.ayers said you can return to the beginning of the line and print something new over the old value.
You can use the readline module, which can also provide customized completion and command history.

Python print statement prints nothing with a carriage return

I'm trying to write a simple tool that reads files from disc, does some image processing, and returns the result of the algorithm. Since the program can sometimes take awhile, I like to have a progress bar so I know where it is in the program. And since I don't like to clutter up my command line and I'm on a Unix platform, I wanted to use the '\r' character to print the progress bar on only one line.
But when I have this code here, it prints nothing.
# Files is a list with the filenames
for i, f in enumerate(files):
print '\r%d / %d' % (i, len(files)),
# Code that takes a long time
I have also tried:
print '\r', i, '/', len(files),
Now just to make sure this worked in python, I tried this:
heartbeat = 1
while True:
print '\rHello, world', heartbeat,
heartbeat += 1
This code works perfectly. What's going on? My understanding of carriage returns on Linux was that it would just move the line feed character to the beginning and then I could overwrite old text that was written previously, as long as I don't print a newline anywhere. This doesn't seem to be happening though.
Also, is there a better way to display a progress bar in a command line than what I'm current trying to do?
Try adding sys.stdout.flush() after the print statement. It's possible that print isn't flushing the output until it writes a newline, which doesn't happen here.
Handling of carriage returns in Linux differs greatly between terminal-emulators.
Normally, one would use terminal escape codes that would tell the terminal emulator to move the virtual "carriage" around the screen (think full-screen programs running over BBS lines). The ones I'm aware of are the VT100 escape codes:
\e[A: up
\e[B: down
\e[C: right
\e[D: left
\e[1~: home
\e[4~: end
Where \e is the escape character, \x1b.
Try replacing all \r's with \e[1~
Also see this post
If your terminal is line-buffered, you may need a sys.stdout.flush() to see your printing if you don't issue a linefeed.

Categories