Python '\r' print on the same line but won't erase the previous text - python-3.x

I am trying to print the report for each iteration. Since each iteration takes a really long time to run, therefore, I use print together with end="\r" to show the current item being processed.
Here's the dummy code:
import time
y = list(range(50))
print("epoch\ttrain loss\ttest loss\ttrain avg\ttest avg\ttime\tutime")
for e in range(10):
for i in range(50):
print("training {}/{} batches".format(i,50), end = '\r')
time.sleep(0.05)
print('{}\t{:2f}\t{:2f}\t{:2f}\t{:2f}\t{:2.1f}\t{:2.1f}'.format(y[0]+e,y[1]+e,y[2]+e,y[3]+e,y[4]+e,y[5]+e,y[6]+e))
Expected Result
This is my expected result, where the progress information is completely erased after each iteration. (I am running it in Jupyter notebook, and it looks fine)
The Result that I am getting
However, when I run it on linux terminal, the progress information is not completely erased, and the result is overlaying on top of the progress.
Why is it so? How to solve it?

\r simply moves the cursor back to the beginning of the current line. Anything printed after the \r is printed "on top of" the content previously there. On a real printer/teletype this would be literally true, with two characters getting printed in the same position ("overstruck"). On a terminal, the new characters replace the old ones (but only in positions that you actually write to).
You can take advantage of this behavior of terminals by printing spaces. You need at least as many spaces as the content you want to erase, but not enough to make the terminal wrap to the next line (this may be impossible if the line was printed all the way to the last character).
In your case, you know that the line won't be more than 22 characters long, so you could use end='\r \r' (go back to the beginning of the line, print 22 blanks, then go back to the beginning of the line again).

\r option will set (move) the cursor to start. It will not clear the text.
You have to make sure your printed data has enough space to overwrite the previous printed data or be of the same length since just moving to the same line would not automatically clear the previous contents.

Related

Norminette empty line or not at end

Why people on VStudio with norminette highlights put an empty line at end.
And when they do norminette in iTerm it’s Works
When you use Vim and put an empty line at end the norminette say Error extra line.
This happen yesterday and today my Vstdio ask for a line at end and when I do norminette in iTerm it’s say error extra line. I go back to vim, delete the line and norminette say error again to remove extra line. I need to open back the file, add line and then delete and save to have norminette working. So now sometime moulinette say KO on server but OK my side. I need to add/remove last line every time with vim when I work on vstdio
So if someone know the issue i would like to have a better solution than double check on vim for the next 3 week and maybe 3 years 🤣 thx all!
That topic has already been discussed to death.
No matter what system you are on, lines in text files generally end with one or two invisible characters. On some systems, it's a "carriage return" CR followed by a "line feed" LF, on other systems it's only a CR, on other systems it's only a LF, and that's only for the least exotic ones. That character or pair of characters has a few colloquial names: "newline", "EOL", etc. I will use "EOL" from now on.
Now, EOL has two semantic interpretations. In some contexts, EOL is considered to be a "line terminator", meaning that no assumption is made about what comes after it, and in some other contexts, EOL is considered to be a "line separator", meaning that there is always a line after it.
And then there is the related problem of how a stream of text should end. With the first interpretation, the last line of a stream should end with EOL, if only to be able to establish a boundary between two streams. With the second interpretation above, the last line of a stream shouldn't end with EOL because it would mean… that the last line is not really the last line.
So, basically, this text:
foo
bar
baz
could be encoded as (first interpretation):
foo<EOL>
bar<EOL>
baz<EOL>
or as (second interpretation):
foo<EOL>
bar<EOL>
baz
Most Unix-like tools have adopted the first interpretation for decades and generally expect EOL on the last line but many more modern tools have adopted the second interpretation, which leads to much confusion among new generations who juggle between GUI editors and CLI tools.
Feed some text with a final EOL to a tool that interprets it as a "line separator" and you get an imaginary line displayed at the end of the file:
1 foo
2 bar
3 baz
4
Feed some text without a final EOL to a tool that interprets it as "line terminator" and you can get anything from a reasonable display (as follows) to loud complaints (git):
1 foo
2 bar
3 baz
Add to that confusing names like "newline" and you have a recipe for a never-ending stream of questions like this one.
So… this is what seems to be going on, here:
you are using a mix of tools that interpret EOL differently,
you are interpreting one of those interpretations incorrectly,
and you act upon that misinterpretation, with confusing results.
Let's address these one-by-one.
Well, we all do so ¯\_(ツ)_/¯.
What appears like an extra line at the bottom of your file in a modern GUI editor is unlikely to be an extra line. It is more likely to be an artefact of the second interpretation. Assuming you are on some kind of Unix-like system and the expected EOL is LF, you can do $ xxd filename to inspect its content in hexadecimal form:
a single a0 at the end means that your file ends with EOL,
a a0a0 at the end means that your file has an extra empty line,
no a0 at the end means that it was written by a an editor that firmly adheres to the second interpretation.
The second case will angry your linter:
Error: EMPTY_LINE_EOF (line: 7, col: 1): Empty line at end of file
but it doesn't seem to particularly care about the other two cases.
Because you see what appears to be an empty line at the end of a file in a GUI editor it doesn't mean that a) that line actually exists and b) that you must add one at the end of the file in Vim or any other editor.
The correct approach is to:
let Vim do what it does out the box, write files with an EOL at the end, because that's what your toolchain (including Norminette) expects,
set up your GUI editors to do the same (even if they still show that imaginary line),
get rid of any extraneous empty line you might have in one of your projects,
NEVER add an extraneous empty line at the end of your files, as it useless at best and forbidden at worst.

Why does my code run successfully but give not output?

I am new to python. I am trying to open a text file with name 'P' and show the lines as an output. I wrote the code below, and it runs but not output. Why is this so?
with open('/Users/LENOVO/Desktop/P.txt','rt') as a_file:
for lines in a_file.readlines():
print(lines,ends='')`
because your print contains end=""
usually the \n is used to flush the output.
if you want to force it to flush the buffer (so to print it without the \n) you can add the flush option :
print(lines,end='', flush=True)
But maybe you just want to remove the end keyword:
print(lines)
When to use end=''?
When you use the end parameter you replace the usual \n (carret return) by something else, that is useful if you want to display a série of things next to each other without going next line everytime. (for instance if you want to print a dot . or x for each call to a function that you're calling in a loop for a big number of times.
And yes it should be end and not ends
See reference here :
https://www.w3schools.com/python/ref_func_print.asp
I do not know where you got ends='' from, but if you remove it, it produces an output.
I also figured I would also add that you are most likely referring to end, this will essentially just replace the \n which is the default value with whatever you wish.

Is there an end= equivalent for inputs?

So as I'm sure you know there's a specific operator for print() functions called end.
#as an example
print('BOB', end='-')
#would output
BOB-
So is there something like this for inputs? For example, if I wanted to have an input that would look something like this:
Input here
►
-------------------------------------------------------
And have the input at the ► and be inside the dashes using something like
x = input('Input here\n►', end='-------')
Would there be some equivalent?
EDIT:
Just to be clear, everything will be printed at the same time. The input would just be on the line marked with the ►, and the ---- would be printed below it, but at the SAME time. This means that the input would be "enclosed" by the ---.
Also, there has been a comment about curses - can you please clarify on this?
Not exactly what you want, but if the --- (or ___) can also be on the same line, you could use an input prompt with \r:
input("__________\r> ")
This means: print 10 _, then go back \r to the beginning of the line, print > overwriting the first two _, then capture the input, overwriting more _. This shows the input prompt > ________. After typing some chars: > test____. Captured input: 'test'
For more complex input forms, you should consider using curses.
When using basic console IO, once a line has been ended with a newline, it's gone and can't be edited. You can't move the cursor up to do print anything above that last line, only add on a new line below.
That means that without using a specialized "console graphics" library like curses (as tobias_k suggests), you pretty much can't do what you're asking. You can mess around a little with the contents of the last line (overwriting text you've already written there), but you can't write to any line other than the last one.
To understand why console IO works this way, you should know that very early computers didn't have screens. Instead, their console output was directly printed out one line at a time on paper. While some line printers could print several characters on the same spot (to get effects line strikethrough or underline), you couldn't unprint anything once it was on the paper. Furthermore, the paper feed only worked in one direction. Once you had sent a newline character that told the printer to advance the paper, you couldn't go back to an old line again.
I believe this would solve your problem:
print(f">>> {input()} ------")
OR
print(f"{input(">>>")} ------")
F-strings are quite useful when it comes to printing text + variables.

Why does MacVim show `#` and blank space for long strings?

This drives me really insane...
Say I have a short line of text on line 32, and a very long string on line 33, say 10,000 characters long... if I have word-wrap on, it ONLY shows line 32 and stops there, and instead of displaying 33+ it just displays # in the first column and all the rest is whitespace.
I have to move the cursor all the way to the very bottom and then the entire string appears at once.
This is extremely jarring because if you 'overshoot' when scrolling, it immediately disappears again.
I want it to behave sanely... where nothing jumps in or out of the screen all at once. It should just flow along like normal with all the other line numbers, and always be visible.
The answer was I needed to add this:
" show as much of long lines as possible
:set display+=lastline

How to manually mark lines and store to register

What is an easy way to manually mark arbitrary lines and yank/delete them without writing to the document?
Eg line 10,17,33 in a 50 line document. Without using the line numbers, though.
My workaround so far:
I put a unique string at the beginning of the lines, eg x and
:g/^x/y R
yank them to a register (r in this case)
After putting I still have to delete the string
:s/^x//g
How can this be done better and without temporarily changing the document?
EDIT:
I want to keep the advantages of this method:
Keep the original order regardless of the order I marked the lines
I can see which lines are marked already
The fewer keystrokes per line the better, of course
If it's no more than 26 locations in the buffer, I would mark them with lowercase marks (ma, mb, ...), then step through them from the beginning of the buffer with ]' while yanking them into an uppercase register:
gg]'"ryy]'"Ryy]'"Ryy...
Unfortunately, ]' doesn't beep when there's no more mark, so you cannot employ a recursive macro that would automatically stop.
Move the cursor to the first line, do "Ryy, repeat.

Resources