Here is a sample solution for your reference. You can use the decorator here to decorate any function that you want to put a timeout on.
from datetime import datetime, timezone
import multiprocessing
import time
def timeout(seconds):
def decorator(func):
def wrapper(*args, **kwargs):
response = multiprocessing.Manager().dict()
proc = multiprocessing.Process(target=func, args=(*args, response), kwargs=kwargs)
proc.start()
start = time.time()
while (time.time() - start) < seconds and proc.is_alive():
pass
if proc.is_alive():
print(f"Process is not finished after {seconds} seconds. Terminating...")
proc.terminate()
proc.join()
return dict(response)
return wrapper
return decorator
@timeout(10)
def scan_nfc_card(card_name, response):
# If you need to return anything from the function with a timeout, use the response dictionary.
response['counter'] = 0
while True:
response['counter'] += 1
print(f"Waiting for NFC card {card_name} to be scanned...")
time.sleep(1)
print(f"[{datetime.now(timezone.utc)}] Start first process")
response = scan_nfc_card("card-ABC")
print(f"{response=}")
print(f"[{datetime.now(timezone.utc)}] Continue other processes")
Output:
$ python3 script.py
[2021-09-02 10:23:50.475114+00:00] Start first process
Waiting for NFC card card-ABC to be scanned...
Waiting for NFC card card-ABC to be scanned...
Waiting for NFC card card-ABC to be scanned...
Waiting for NFC card card-ABC to be scanned...
Waiting for NFC card card-ABC to be scanned...
Waiting for NFC card card-ABC to be scanned...
Waiting for NFC card card-ABC to be scanned...
Waiting for NFC card card-ABC to be scanned...
Waiting for NFC card card-ABC to be scanned...
Waiting for NFC card card-ABC to be scanned...
Process is not finished after 10 seconds. Terminating...
response={'counter': 10}
[2021-09-02 10:24:00.502205+00:00] Continue other processes
- As you can see, the function reached the timeout of 10 seconds.
Let's say the NFC scan was successful right away
@timeout(10)
def scan_nfc_card(card_name, response):
response['counter'] = 0
while True:
response['counter'] += 1
print("Waiting for NFC card to be scanned...")
break # Break right away
Output:
$ python3 script.py
[2021-09-02 10:23:43.343436+00:00] Start first process
Waiting for NFC card card-ABC to be scanned...
response={'counter': 1}
[2021-09-02 10:23:43.385748+00:00] Continue other processes
- Now, the function ended right away.