简体   繁体   中英

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM