2
\$\begingroup\$

The method to overwrite the same line is well known and I use it for countdown, but what about when the next output string has a different size and will be generated by a single print? That's the reason for my question!

I use a text countdown timer like (all on the same line):

Next activation in 5 seconds
Next activation in 4 seconds
Next activation in 3 seconds
Next activation in 2 seconds
Next activation in 1 seconds

In order not to waste unnecessary lines, I created a false way to produce the same result as the keyboard backspace button (false because it actually only writes over the top with blank spaces, giving the false impression that we return to the first position left writing in the terminal):

import sys
import time
from datetime import datetime
def main():
 while True:
 print('-------- test --------')
 print(datetime.now().strftime('%Y/%d/%m %H:%M'))
 for remaining in range(5, 0, -1):
 sys.stdout.write('\r')
 txt_value = f'Next activation in {remaining:2d} seconds'
 sys.stdout.write(txt_value)
 sys.stdout.flush()
 time.sleep(1)
 sys.stdout.write('\r' + len(txt_value)*' ')
 sys.stdout.write('\r')
if __name__ == '__main__':
 main()

Output countdown:

-------- test --------
Next activation in 5 seconds

Output after full countdown:

-------- test --------
20221806 21:21

It's a pretty archaic method (at least I imagine it is), so I brought this question for improvements and professionalization of the method.

200_success
145k22 gold badges190 silver badges478 bronze badges
asked Jun 20, 2022 at 12:35
\$\endgroup\$
4
  • \$\begingroup\$ ERASE_LINE = '\x1b[2K'; sys.stdout.write(ERASE_LINE) see ANSI Escape Sequences. \$\endgroup\$ Commented Jun 20, 2022 at 14:17
  • \$\begingroup\$ Hi @JosefZ this method generate a multiple blank space before new print: . -------- test -------- (I had to add a dot . at the beginning because the formatting ignores whitespace at the beginning) \$\endgroup\$ Commented Jun 20, 2022 at 14:22
  • \$\begingroup\$ sys.stdout.write('\r' + ERASE_LINE) or sys.stdout.write(ERASE_LINE + '\r'). There are no spaces at the erased line however the cursor position does not change by ERASE_LINE itself. \$\endgroup\$ Commented Jun 20, 2022 at 14:41
  • \$\begingroup\$ Perfect, I understood the process indicated by you, thank's @JosefZ ! \$\endgroup\$ Commented Jun 20, 2022 at 14:46

1 Answer 1

1
\$\begingroup\$

ANSI escape sequences are not necessary, and the so-called archaic method of using a carriage return is preferred.

Avoid mixing sys.stdout with print; prefer the latter. This offers a flush kwarg to be used instead of sys.stdout.flush().

For the purposes of demonstration it's best if you include a seconds-field in your timestamp.

Think about the assumptions of print(). It has a default ending character of a linefeed. A more uniform approach to printing uses either a terminating linefeed or a terminating carriage return, not a prefix carriage return. During the sleeping period, the carriage return will have the cursor sitting at the beginning of the line, ready to overwrite with either another progress banner or real output.

Suggested

from time import sleep
from datetime import datetime
def main():
 progress_len = 0
 while True:
 print(
 f'{"-------- test --------":{progress_len}}\n'
 f'{datetime.now():%Y/%d/%m %H:%M:%S}'
 )
 for remaining in range(5, 0, -1):
 txt_value = f'Next activation in {remaining:2d} seconds'
 progress_len = len(txt_value)
 print(txt_value, end='\r', flush=True)
 sleep(1)
if __name__ == '__main__':
 main()
answered Jun 20, 2022 at 15:04
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.