-1

I have a function func and that func can run from 2 to 8 seconds, and i have interval.

both of func and interval is Multithreading

if func runs less than 5 seconds loop next, if func takes greater than 5 seconds break continue loop.

How can I do that? Thanks.

def func():
    global che
    x = random.randint(2, 8)
    time.sleep(x)
    print('Time sleep: ', x)
    che = True


def interval(tg):
    global che2
    time.sleep(tg)
    print('INTERVAL: ', tg)
    che2 = True

inter = 5

for i in range(1, 6):
    che = False
    che2 = False
    print('-------------------------------STEP--------------------------------')
    T1 = threading.Thread(target=interval, args=(inter,))
    T2 = threading.Thread(target=func)
    T1.start()
    T2.start()
    T1.join()
    T2.join()
    if che or che2:
        continue

I want either one of the two to work.

Tú Phan
  • 13
  • 4
  • i think this might be a duplicate of https://stackoverflow.com/questions/73860734/how-to-stop-the-sleep-function – Joran Beasley Sep 28 '22 at 04:04
  • @Joran Beasley. Sorry, I think this is one thread, and i want two threads from module Thread, loop for 2 func if 1 of 2 run complete it is break(continue) – Tú Phan Sep 28 '22 at 04:13
  • 1
    you cannot interrupt sleep ... so that thread will continue until the sleep is complete ... with multiprocess you can typically terminate and it will work for most code... threading cannot really terminate externally – Joran Beasley Sep 28 '22 at 04:16
  • Actually I want loop a func but it is can run time from 2 to 10s and i want have a other thread check if time exceeded 5 seconds it's break(continue) – Tú Phan Sep 28 '22 at 04:21
  • 1
    with your current program structure it simply will not work ... you need to change to multiprocessing and use something like a shared variable(not a global... see https://stackoverflow.com/questions/17377426/shared-variable-in-pythons-multiprocessing ) to get data out instead of using a global – Joran Beasley Sep 28 '22 at 05:15

2 Answers2

1

I think you will need to use multiprocessing as it allows you to "terminate" a process early(where i think threading might work on unix/linux but not windows to terminate early, and is somewhat inconsistent in early termination) ... here is a naive implementation of your code above (note that sleep is a pretty bad example for this sort of thing since it is not very interruptable...)

some things to note ...

  • multiprocessing CANNOT access global variables how you were earlier (I used multiprocessing.Value's, but you could solve this with pipes or queues as well)
  • the "main" block that spawns the processes MUST be protected by the __main__ guard

without further ado

import multiprocessing
import time
import random

def func(variable):
    """

    :param variable: a multiprocessing.Value to set to 1 if this function finishes...
    :return:
    """
    x = random.randint(2, 8)
    time.sleep(x)
    print('Time sleep: ', x)
    variable.value = 1 # now it is 1 (or True)


def interval(tg, otherFlag):
    """

    :param tg: time to wait
    :param otherFlag: multiprocessing.Value to be set to 1 if this function finishes...
    :param targetProcess: the target process to kill if it is taking too long
    :return:
    """
    time.sleep(tg)
    otherFlag.value = 1 # terminated...

if __name__ == "__main__":
    inter = 5

    for i in range(1, 6):
        mgr = multiprocessing.Manager()
        che = mgr.Value('B',0)
        che2 = mgr.Value('B',0)

        print('-------------------------------STEP--------------------------------')
        T1 = multiprocessing.Process(target=interval, args=(inter,che2))
        T2 = multiprocessing.Process(target=func,args=(che,))
        T1.start()
        T2.start()
        # lets do a more manual join
        while T1.is_alive() and T2.is_alive():
            if not T1.is_alive():
                print("T1 finished first ... kill T2")
                T2.terminate()
            elif not T2.is_alive():
                print("T2 finished first ... kill T1")
                T1.terminate()
        print(che.value,che2.value)
Joran Beasley
  • 110,522
  • 12
  • 160
  • 179
  • Thank you very much. And I will understand it. and I can only take time.sleep as an example because i have a function by selenium it can take a long time and i want to give my allotted time – Tú Phan Sep 28 '22 at 06:48
0

I'm not sure

import time
import random
import multiprocessing


def func(a, name, age):
    global che
    start_time = time.time()
    x = random.randint(100000000, 200000000)
    for i in range(x):
        i *= i
    print('Time sleep', time.time() - start_time, a, end=' ')
    print(f'Name: {name} Age: {age}')
    che = True

def interval(a):
    global che2
    for i in range(110000000):
        i *= i
    print('INTERVAL', a)
    che2 = True


if __name__ == '__main__':
    inter = 3
    for i in range(5):
        che = False
        che2 = False
        g1 = multiprocessing.Process(target=interval, args=(i, ))
        g2 = multiprocessing.Process(target=func, args=(i, 'Phan Tu', 22))
        print('-------------------------------STEP--------------------------------')
        g1.start()
        g2.start()
        while g1.is_alive() and g2.is_alive():
            if not g1.is_alive():
                g2.terminate()
                continue
            if not g2.is_alive():
                g1.terminate()
                continue

output:

-------------------------------STEP--------------------------------
INTERVAL 0
-------------------------------STEP--------------------------------
Time sleep 7.687726736068726 0 Name: Phan Tu Age: 22
INTERVAL 1
-------------------------------STEP--------------------------------
Time sleep 5.987775802612305 1 Name: Phan Tu Age: 22
INTERVAL 2
-------------------------------STEP--------------------------------
Time sleep 6.6201207637786865 2 Name: Phan Tu Age: 22
INTERVAL 3
-------------------------------STEP--------------------------------
INTERVAL 4
Time sleep 5.269529104232788 4 Name: Phan Tu Age: 22

Process finished with exit code 0
Tú Phan
  • 13
  • 4