Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Apscheduler not stopping function execution

I'm trying to execute my face detection function and use Apscheduler to run the function only between certain time. I can start the function correctly but the end_time parameter doesn't seem to work at all, the function just keeps on running until shutted down manually.

Here is the route which starts the schedule:

@app.route("/schedule/start", methods = ['POST'])
    def create():
        sched = BlockingScheduler()
        sched.add_job(detection, 'cron', start_date='2020-10-01 15:33:00', end_date='2020-10-01 15:33:05')

    sched.start()


    return 'Schedule created.'

I have a While True condition in my detection -function, all the detetion logic run inside it. Could that be the reason why it never stops even if I have determined the stop time? How could I fix this issue?

Edit. While -loop from my detection -function (removed unnecessary parts):

while True:
        
    frame = stream.read()

    frame = imutils.resize(frame, width=900)
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    frame = np.dstack([frame, frame, frame])
    # frame = cv2.flip(frame, 0)
    faces = faceCascade.detectMultiScale(
                        frame,
                        scaleFactor=1.1,
                        minNeighbors=3,
                        # minSize=(10, 10),
                        # maxSize=(50, 50),
                        # flags=cv2.CASCADE_SCALE_IMAGE
                )

    for (x, y, w, h) in faces:
        name = str(currentframe) + '.jpg'
        print('Creating...' + name)
        cv2.imwrite(os.path.join(parent_dir, name), frame)

        currentframe += 1

        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

Edit2. I tried as suggested below and got this error: TypeError: func must be a callable or a textual reference to one.

I would also like to integrate a ability to manually start and stop my face detection function. I'm able to do it like this:

@app.route("/start", methods = ['POST'])
def start():
    os.environ['run'] = 'running'
    detection()

    return 'Detection started'


@app.route("/stop", methods = ['POST'])
def stop():
    os.environ['run'] = 'stop'    

    return 'Detection stopped.'

And then in my detection.py I just check the environment variable in the beginnig of my while-loop:

while True:
        if os.environ.get('run') == 'stop':
            stream.stream.release()
            exit()

What I'd want would be to integrate the scheduling feature to this. I wouldn't want to have to make separate functions because I want to be able to manually stop the detection started with schedule. Any tips how I could achieve this?

Edit3. The schedule is working now. Manual start works also and stopping works in a mean that it stops detecting faces. The function started with schedule still keeps going though, it just doesn't iterate to the detection part at all because there is a os.environ['run'] = 'stop' -flag. Any idea how I could stop the function execution? This is the while -loop check I have:

while True:
    if self.end_date <= datetime.now() or os.environ.get('run') == 'stop':
        stream.stream.release()
        exit()

When manually started, the stop function works as supposed, but when stopping a scheduled job, it keeps looping until the end_date time is met.

like image 339
lr_optim Avatar asked Sep 17 '26 04:09

lr_optim


1 Answers

You need to have some condition that will end your while loop as it's infinite now, pass start/end times and convert to date-time and try to match while end_date_time =< now: then quit the task. If you need to pass start/end dates, maybe convert the your detection function to class and on initialization pass the end_date when you want your cron job to stop.

# detection.py
from datetime import datetime

class Detection:
    def __init__(self, end_date):
        self.end_date = datetime.strptime(end_date, '%Y-%m-%d %H:%M:%S.%f')

    def detection(self):
        print(self.end_date)
        while self.end_date <= datetime.utcnow():
            print('works')



# routes.py
# And then do it like this when starting cron
import Detection

def create():
    start_date = '2020-10-02 01:48:00.192386'
    end_date = '2020-10-02 05:50:00.192386'
    dt = Detection(end_date)
    sched = BlockingScheduler()
    sched.add_job(dt.detection, 'cron', start_date=start_date, end_date=end_date)

    sched.start()


    return 'Schedule created.'



This should resolve the issue

like image 129
simkusr Avatar answered Sep 19 '26 20:09

simkusr



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!