DogeCode
DogeCode

Reputation: 381

Continue executing code without interrupting output of looping function

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()

Upvotes: 0

Views: 144

Answers (2)

DogeCode
DogeCode

Reputation: 381

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!')

Upvotes: 0

Doruk Eren Aktaş
Doruk Eren Aktaş

Reputation: 2337

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?

Upvotes: 1

Related Questions