So I am trying to use sys.stdout.write() to rewrite the current line it is on and replace it with different text. But I want this to happen for multiple lines of output.
# I am looking at having 2 lines with changing values in them that will keep over writing themselves without moving any further down.
import sys
for i in range(10):
sys.stdout.write("\r" + "Hello" + str(i) + "\n + "Hello" + str(i) * 2)
sys.stdout.flush()
I tried this but every time it hits the \n it will indefinately increase the numbers of lines without clearing everything.
stdout\stderr don't work like that. You can send control characters to your terminal to delete characters but once a line is sent it's basically fixed.
What you actually need is ncurses which gives you much more control over the display and cursor position when writing to a terminal.
Related
I have written a small tool that iterates over a wordlist and I want it to print each line from the wordlist over the previous line, I have tried the following but it has issues.
print(word + (100 * " "), end="\r", flush=True)
This works as expected in VSCodes in-built terminal but when I run the same tool in either the OS's (Xfce) in-built terminal or Terminator each "word" is printing on a newline
Does anyone know why this is happening all my research just points me on how to do it, which doesn't help as the way to do it is what has this issue.
Thanks
This is because depending on your window width (and word length), each string may be longer than the line. So the next print statement is 'overwriting' the previous string, but since that previous string jumped a line, so the new string starts on that new line.
You can see this in action by printing 99 spaces followed by a * or some other character:
print(word + (99 * " ") + "*")
Depending on your window width and word length, this may or may not jump a line, as demonstrated by where there "*" prints.
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.
I am using '\r' in print function in python 2.7. It works fine in terminal but not in terminator.
For example:
I am using a decrement counter which decrements from n to 0. In the Terminal, the count values are updated at the same line while in terminator, it count values get printed on new line. I am using terminator for various reasons such as its advanced features like tab partitioning etc. Below is the code snapshot
import sys
import time
if __name__ == "__main__":
sleep_time_in_sec = 15
time_to_go_back_mns = 10
for remaining in range(sleep_time_in_sec, -1, -1):
sys.stdout.write("\r")
sys.stdout.write(
"{:2d} seconds remaining to read last {:2d} minutes of data and perform prediction .....".format(remaining,
time_to_go_back_mns))
sys.stdout.flush()
time.sleep(1)
Can someone please suggest a fix
Simply place the \r at the end of your write statement like so:
sys.stdout.write(
"{:2d} seconds remaining to read last {:2d} minutes of data and perform prediction .....\r".format(remaining,
time_to_go_back_mns))
New data will then overwrite the line, you can use flush() to clear the line before writing to it again:
sys.stdout.flush()
Make sure that on the terminator side of things your profile settings are clean. Be sure to check out the compatibility tab as it mentions weird application behaviour.
note that carriage return stops functioning if the terminal size is too small. It will only return to the first character of the LAST line
Original answer
\r actually means "carriage return" whereas \n is a line feed.
In Linux (Unix) you'd usually use either a \n or \r\n.
So if your goal is to go to a new line you should use \n instead.
The reason it might work in the "terminal" (whichever one that might be) is because some terminals (notably gnome's terminal) catches the \r and treats it as a \r\n.
The answer for this post goes to #Rick van Lieshout.
In my case, I was using multiple tabs in the same window as a result of which \r was not working. It worked fine when I used it in a separate window or a tab with full horizontal width.
I just want to know why it's doing this, and how to fix it.
I've tried changing the screen size and it still doesn't work.
Any Ideas?
If you try to run the code, choose option C as that's the one that doesn't work for me. It's meant to print off all the moderate/high client's times, but it puts the total time on a new line.
Code + files:
Text file
Python code
Print statements automatically append "\n" to the end of the statement. This ensures that the next print statement will write to a new line instead of on the previous line.
If you want to prevent this, you can use this parameter:
print("This is a: ", end="")
print("message")
Notice the end="" on the first print statement. This will output
This is a: message
If that doesn't solve your issue, I suggest taking a close look at the text you're printing. Make sure that none of the lines have a "\n". Note that reading text from a .txt file will yield lines that automatically have "\n" appended to them.
This is a question for python language, and the terminal/console applies to Unix-like systems. It would be great if the solution is platform independent but that is not required.
The scenario is when the program keeps printing lines to terminal. However, among the many lines to print, some of them are special, like progress bar or status indicator: they have to be placed only at the bottom of the console, while all other lines can still be printed where they normally are, one after another and the screen scrolls as normal too.
An example code solution would be much better than a theoretic one. For this purpose here is an example:
def print_status(msg):
# implement me
print msg
def print_many_lines():
print 'line one\n'
print 'line two\n'
print_status('i am here')
print 'line three\n'
print 'line four\n'
print 'line five\n'
print_status('i am changed')
print 'line six\n'
Could you help me implement the print_status function so that the msg passed to it will always be printed at the bottom of terminal?
Please note that this is very different from another similar question that, when multiple lines are printed consecutively to the terminal, how can we make sure they are printed at the same line. Using \r can be useful in that scenario but it cannot solve this problem, because (1) these special lines may more likely not be printed consecutively and (2) there will be other lines printed after these special lines but these special lines should be kept at the bottom of terminal, still.
Thanks!
For a Windows terminal try the console module For unix the curses module would do.
This is how you do it on Windows.
c = Console.getconsole()
c.text(0, -1, 'And this is the string at the bottom of the console')
By specifying -1 for the second argument, string goes at bottom line.
For Linux, a working code which prints at last line.
import time
import curses
def pbar(window):
height, width = window.getmaxyx()
for i in range(10):
window.addstr(height -1, 0, "[" + ("=" * i) + ">" + (" " * (10 - i )) + "]")
window.refresh()
time.sleep(0.5)
curses.wrapper(pbar)
It sounds like you want to use a curses library, which handles text based UIs on Unix systems. There's a module for it in python's standard library:
https://docs.python.org/2/library/curses.html#module-curses
How to use it is beyond the scope of an answer here I'm afraid.