0

I have a while loop counting in centiseconds and printing the current_step var, always on the same line.

I want to run, for example,

x = True

while x is True:
    pass #printing timer to CLI here

print('this is more code running while the timer is still running')
input('Press enter to stop the timer')
x = False
#When x becomes False, I want the while loop to terminate

I know this must involve subprocess or something of the likes, but I don't know what direction to point myself in for learning to solve this issue.

Here is the function for reference:

def timer(stawt, stahp, step, time_step):
    from time import sleep

    stawt = int(stawt)
    stahp = int(stahp)

    if stahp < 1:
        stahp = 1
    elif stahp > 1000:
        stahp = 1000

    stahp = stahp * 100 + 1
    titerator = iter(range(stawt, stahp, step))

    while True:
        try:
            current_step = str(next(titerator))
            if int(current_step) < 99:
                final_time = '0' + current_step[:0] + '.' + current_step[0:] + 's'
                print('\r' + final_time, end='')
            elif int(current_step) < 999:
                final_time = current_step[:1] + '.' + current_step[1:] + 's'
                print('\r' + final_time, end='')
            elif int(current_step) < 9999:
                final_time = current_step[:2] + '.' + current_step[2:] + 's'
                print('\r' + final_time, end='')
            else:
                final_time = current_step[:3] + '.' + current_step[3:] + 's'
                print('\r' + final_time, end='')

            sleep(time_step)
        except:
            print(); break

    seconds = int((int(current_step) / 100) % 60)
    minutes = int((int(current_step) / 100) // 60)

    if minutes < 1:
        return ''
    else:
        final_time_human = str(minutes) + 'm ' + str(round(seconds)) + 's'
        print(final_time_human + '\n')

def MAIN():
    count_to = float(input('Enter max number of seconds to count:\n'))

    print()
    timer(0, count_to, 1, 0.01)

MAIN()
DogeCode
  • 346
  • 2
  • 10
  • you just want to print on the same line? or you want to run async? – bherbruck Jun 02 '20 at 03:04
  • async i believe. The timer is continuously erasing the line it last print with the current_step var. While that is looping, I would like other commands to occur simultaneously; I want these commands to be able to print stdout and stderr to the shell without disrupting the timer's line that is being reprinted every 10ms. If this means multiple threads need to be used, I want the threads to share that x boolean at the top of my original question. – DogeCode Jun 02 '20 at 03:07

2 Answers2

1

You need to use threading.

import threading

x = True

def thread_function():
    while x is True:
        pass #printing timer to CLI here

threading.Thread(target=thread_function).start()

# Continue with the other steps you want to take
# ...


# This will terminate the timer loop
x = False

Python threading documentation: https://docs.python.org/3/library/threading.html

If you want to print the time always at the same line you need to control terminal cursor. For more information checkout: How can move terminal cursor in Python?

Doruk Eren Aktaş
  • 2,121
  • 8
  • 23
0

Thanks to @dorukerenaktas, I have got this working. This is their answer adapted into my scriptlet:

import threading
from os import system

timer_thread = None

def timer(stawt, stahp, step, time_step):
    from time import sleep
    global run_timer

    stawt = int(stawt)
    stahp = int(stahp)

    if stahp < 1:
        print('Sorry, I limit min count to 1 second!\n')
        stahp = 1
    elif stahp > 1000:
        print('Sorry, I limit max count to 1000 seconds!\n')
        stahp = 1000
    else:
        print()

    stahp = stahp * 100 + 1
    titerator = iter(range(stawt, stahp, step))

    def print_time():
        while run_timer is True:
            try:
                current_step = str(next(titerator))
                if int(current_step) < 99:
                    final_time = '0' + current_step[:0] + '.' + current_step[0:] + 's'
                    print('\r' + final_time, end='')
                elif int(current_step) < 999:
                    final_time = current_step[:1] + '.' + current_step[1:] + 's'
                    print('\r' + final_time, end='')
                elif int(current_step) < 9999:
                    final_time = current_step[:2] + '.' + current_step[2:] + 's'
                    print('\r' + final_time, end='')
                else:
                    final_time = current_step[:3] + '.' + current_step[3:] + 's'
                    print('\r' + final_time, end='')

                sleep(time_step)
            except:
                break

        seconds = int((int(current_step) / 100) % 60)
        minutes = int((int(current_step) / 100) // 60)

        if minutes < 1:
            return ''
        else:
            final_time_human = str(minutes) + 'm ' + str(round(seconds)) + 's'
            print('\n' + final_time_human)

    print_time()

def _init_timer():
    global run_timer; run_timer = True
    global timer_thread

    print('Enter max number of seconds to count: ', end='')
    count_to = float(input())

    timer_thread = threading.Thread(target=timer, args=(0, count_to, 1, 0.01))
    timer_thread.start()

    print('\rPress enter to stop the timer:')
    usr_input = input(); run_timer = False

system('clear')
_init_timer()

timer_thread.join()
print('\nGoodbye!')
DogeCode
  • 346
  • 2
  • 10