#python #flask #scheduled-tasks #apscheduler
#python #flask #запланированные задачи #apscheduler
Вопрос:
Я пытаюсь выполнить свою функцию распознавания лиц и использовать Apscheduler для запуска функции только между определенным временем. Я могу запустить функцию правильно, но end_time
параметр, похоже, вообще не работает, функция просто продолжает работать, пока не будет отключена вручную.
Вот маршрут, который запускает расписание:
@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.'
У меня есть While True
условие в моей detection
функции, вся логика определения выполняется внутри нее. Может ли это быть причиной, по которой он никогда не останавливается, даже если я определил время остановки? Как я могу исправить эту проблему?
Редактировать. Цикл While из моей detection
функции (удалены ненужные части):
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) amp; 0xFF == ord('q'):
break
Редактировать2. Я попробовал, как предложено ниже, и получил эту ошибку: TypeError: func must be a callable or a textual reference to one
.
Я также хотел бы интегрировать возможность ручного запуска и остановки моей функции распознавания лиц. Я могу сделать это так:
@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.'
А затем в моем detection.py
я просто проверяю переменную среды в начале моего цикла while:
while True:
if os.environ.get('run') == 'stop':
stream.stream.release()
exit()
Я бы хотел интегрировать в это функцию планирования. Я бы не хотел создавать отдельные функции, потому что я хочу иметь возможность вручную останавливать обнаружение, начатое с schedule . Любые советы, как я мог бы этого добиться?
Редактировать3. Теперь расписание работает. Ручной запуск также работает, и остановка работает в том смысле, что она перестает обнаруживать лица. Функция, запущенная с schedule, все еще продолжает работать, хотя она просто вообще не переходит к части обнаружения, потому что есть os.environ['run'] = 'stop'
-flag . Есть идеи, как я мог бы остановить выполнение функции? Это проверка цикла, которую я имею:
while True:
if self.end_date <= datetime.now() or os.environ.get('run') == 'stop':
stream.stream.release()
exit()
При запуске вручную функция остановки работает, как и предполагалось, но при остановке запланированного задания она продолжает цикл до тех пор, пока не будет выполнено время end_date.
Комментарии:
1. Не могли бы вы поделиться фрагментом кода
while True
, который у вас есть вdetection
методе?2. Конечно, отредактировал его в мой вопрос.
3. Время окончания — это только последнее время, когда (повторно) запускается полезная нагрузка. Это не время, когда функция останавливается — в generic в Python такого нет.
4. Что я понял об Apscheduler, он должен останавливать выполнение при выполнении
end_date
параметра. Не могли бы вы, пожалуйста, проверить мое второе редактирование из моего исходного сообщения? Хотелось бы услышать, есть ли у вас какие-либо мысли по этому поводу.
Ответ №1:
У вас должно быть какое-то условие, которое завершит ваш цикл while, поскольку теперь он бесконечен, передайте время начала / окончания и преобразуйте в дату-время и попытайтесь соответствовать while end_date_time =< now:
, а затем завершите задачу. Если вам нужно передать даты начала / окончания, возможно, преобразуйте вашу detection
функцию в класс и при инициализации передайте end_date
, когда вы хотите, чтобы ваше задание cron остановилось.
# 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.'
Это должно решить проблему
Комментарии:
1. Я получаю эту ошибку:
TypeError: func must be a callable or a textual reference to one
2. @ir_optim, я обновил пример кода, проверьте его сейчас
3. Спасибо. Заставил его работать с небольшими изменениями. Не могли бы вы проверить мой edit3 из исходного сообщения, если у вас есть несколько советов по остановке вручную, я хотел бы их услышать!
4. @lr_optim в вашем цикле while у вас есть
os.environ.get('running_flag') == 'stop'
while в заданном вами маршрутеstop
os.environ['run'] = 'stop'
, такrunning_flag != run
что, возможно, это проблема, поскольку циклdetection
while пытается получитьos.environ.get('running_flag')
, и если он не установленNone
, вы пытаетесь сравнитьNone == 'stop'
, что всегдаFalse
.5. Похоже, что route
end()
и thecron-job
не используют одни и те же переменные среды. Вам нужно найти способ передать этоrun='stop'
detection
без использованияos.environ