ফ্লাস্কে প্রতি ঘন্টা চালানোর জন্য কোনও ফাংশন শিডিয়ুল করবেন কীভাবে?


99

আমার একটি ফ্লাস্ক ওয়েব হোস্টিং রয়েছে যাতে cronকমান্ডের অ্যাক্সেস নেই ।

আমি কীভাবে প্রতি ঘন্টা কিছু পাইথন ফাংশন সম্পাদন করতে পারি?

উত্তর:


107

আপনি APScheduler প্যাকেজ (v3.5.3) BackgroundScheduler()থেকে ব্যবহার করতে পারেন :

import time
import atexit

from apscheduler.schedulers.background import BackgroundScheduler


def print_date_time():
    print(time.strftime("%A, %d. %B %Y %I:%M:%S %p"))


scheduler = BackgroundScheduler()
scheduler.add_job(func=print_date_time, trigger="interval", seconds=3)
scheduler.start()

# Shut down the scheduler when exiting the app
atexit.register(lambda: scheduler.shutdown())

নোট করুন যে ফ্লাস্ক যখন ডিবাগ মোডে থাকে তখন এই দুটি সিডিউলার চালু করা হবে। আরও তথ্যের জন্য, এই প্রশ্নটি দেখুন।


4
@ user5547025 কীভাবে শিডিউলটি কাজ করে মনে করুন যে আমি বিষয়বস্তুকে শিডিয়ুল রেখেছি? কীভাবে এটি স্বয়ংক্রিয়ভাবে চলবে?
কিশান মেহতা

4
আমি মনে করি ব্যবহারকারীর দ্বারা প্রস্তাবিত সময়সূচি 5547025 সিঙ্ক্রোনাস কাজের জন্য যা মাস্টার থ্রেডকে ব্লক করতে পারে। এটি ব্লক না হওয়ার জন্য আপনাকে কোনও শ্রমিকের থ্রেড তৈরি করতে হবে।
সাইমন

4
যদি flaskএকটি ছিল App.runonceবা App.runForNsecondsআপনার মধ্যে সুইচ করতে পারে scheduleএবং বোতল রানার, কিন্তু এই ক্ষেত্রে, এখন পর্যন্ত একমাত্র উপায় এই ব্যবহার নয়
lurscher

এর জন্য ধন্যবাদ! __ == "__ প্রধান " নামে যদি আমি এই ফাংশনটি সন্নিবেশ করবো ? এছাড়াও আমরা আমাদের ফাংশনটির সাথে মুদ্রণ_ডেট_টাইম ফাংশনটি প্রতিস্থাপন করতে পারি?
আম্বেলু

প্রতিদিনের সময়সূচী একবারে কীভাবে চালানো যায়?
অরুন কুমার

59

আপনি APSchedulerআপনার ফ্লাস্ক অ্যাপ্লিকেশনটি ব্যবহার করতে পারেন এবং এর ইন্টারফেসের মাধ্যমে আপনার কাজগুলি চালাতে পারেন:

import atexit

# v2.x version - see https://stackoverflow.com/a/38501429/135978
# for the 3.x version
from apscheduler.scheduler import Scheduler
from flask import Flask

app = Flask(__name__)

cron = Scheduler(daemon=True)
# Explicitly kick off the background thread
cron.start()

@cron.interval_schedule(hours=1)
def job_function():
    # Do your work here


# Shutdown your cron thread if the web process is stopped
atexit.register(lambda: cron.shutdown(wait=False))

if __name__ == '__main__':
    app.run()

4
আমি কি একটি নবজাতক প্রশ্ন জিজ্ঞাসা করতে পারেন? কেন নেই lambdaমধ্যে atexit.register?
পিগমালিয়ন

4
কারণ atexit.registerকল করার জন্য একটি ফাংশন প্রয়োজন। যদি আমরা সবে পাস করেছি cron.shutdown(wait=False)আমরা কল করার ফলাফলটি পাস করব cron.shutdown(যা সম্ভবত None)। সুতরাং পরিবর্তে, আমরা একটি শূন্য যুক্তি ফাংশন পাস, এবং এর পরিবর্তে একটি নাম দেওয়ার এবং একটি ব্যবহারের বিবৃতি def shutdown(): cron.shutdown(wait=False) এবং atexit.register(shutdown)আমরা এর পরিবর্তে এটি রেজিস্টার করো ইনলাইন সঙ্গে lambda:(যা একটি শূন্য যুক্তি ফাংশন অভিব্যক্তি ।)
শন ভিয়েরা

ধন্যবাদ সুতরাং সমস্যাটি হ'ল আমরা সঠিকভাবে যদি বুঝতে পারি তবে আমরা ফাংশনে যুক্তিটি পাস করতে চাই।
পিগমালিয়ন

52

আমি অ্যাপ্লিকেশন শিডিয়ুলার ধারণাটি নিয়ে কিছুটা নতুন, তবে আমি এখানে APScheduler v3.3.1 এর জন্য যা পেয়েছি তা কিছুটা আলাদা। আমি বিশ্বাস করি যে সর্বাধিক নতুন সংস্করণগুলির জন্য, প্যাকেজ কাঠামো, শ্রেণীর নাম ইত্যাদির পরিবর্তিত হয়েছে, তাই আমি এখানে একটি নতুন সমাধান দিচ্ছি যা আমি সম্প্রতি তৈরি করেছি, একটি বেসিক ফ্লাস্ক অ্যাপ্লিকেশনটির সাথে সংহত:

#!/usr/bin/python3
""" Demonstrating Flask, using APScheduler. """

from apscheduler.schedulers.background import BackgroundScheduler
from flask import Flask

def sensor():
    """ Function for test purposes. """
    print("Scheduler is alive!")

sched = BackgroundScheduler(daemon=True)
sched.add_job(sensor,'interval',minutes=60)
sched.start()

app = Flask(__name__)

@app.route("/home")
def home():
    """ Function for test purposes. """
    return "Welcome Home :) !"

if __name__ == "__main__":
    app.run()

আমি এই গিস্টটি এখানেও রেখে দিচ্ছি , যদি কারও উদাহরণের জন্য আপডেটগুলিতে আগ্রহ থাকে।

ভবিষ্যতে পড়ার জন্য এখানে কিছু উল্লেখ রয়েছে:


4
এটি দুর্দান্ত কাজ করে, আশা করি আরও বেশি লোকেরা এই থ্রেডটি দেখায় এটি শীর্ষে উপরে ভোট পাবে।
Mwspencer

4
আপনি কি এমন কোনও অ্যাপ্লিকেশনে এটি ব্যবহার করে দেখার চেষ্টা করেছেন যা পাইথনএইনহোয়ার বা অন্য কিছুর মতো ওয়েবে বসে?
Mwspencer

4
ধন্যবাদ, @ এমডব্লিউ স্পেন্সার হ্যাঁ, আমি ব্যবহার করেছি এবং এটি দুর্দান্ত কাজ করে :), যদিও আমি আপনাকে সরবরাহিত আরও বিকল্পগুলি অন্বেষণ করার জন্য পরামর্শ দিচ্ছি apscheduler.schedulers.background, কারণ এটি সম্ভবত আপনার অ্যাপ্লিকেশনের জন্য অন্যান্য দরকারী পরিস্থিতির সম্মুখীন হতে পারে। শ্রদ্ধা।
ivanleoncz

4
অ্যাপটি উপস্থিত থাকার সময়সূচীটি বন্ধ করতে ভুলবেন না
হ্যান্নোভস্কি

4
হ্যালো! আপনি কি এমন পরিস্থিতিতে কিছু পরামর্শ দিতে পারেন যেখানে একাধিক বন্দুকবিজ শ্রমিক রয়েছে? আমি বলতে চাইছি, শিডিউলার প্রতি শ্রমিকের জন্য একবার কার্যকর করা হবে?
এলপাপি 42

13

আপনি আপনার ফ্লাস্ক অ্যাপ্লিকেশনে অন্তর্বর্তী কাজ একীভূত করতে APScheduler এর ব্যাকগ্রাউন্ডশিডুলার ব্যবহার করে চেষ্টা করতে পারেন । নীচে ব্লুপ্রিন্ট এবং অ্যাপ্লিকেশন কারখানা ( init .py) ব্যবহার করা উদাহরণ রয়েছে :

from datetime import datetime

# import BackgroundScheduler
from apscheduler.schedulers.background import BackgroundScheduler
from flask import Flask

from webapp.models.main import db 
from webapp.controllers.main import main_blueprint    

# define the job
def hello_job():
    print('Hello Job! The time is: %s' % datetime.now())

def create_app(object_name):
    app = Flask(__name__)
    app.config.from_object(object_name)
    db.init_app(app)
    app.register_blueprint(main_blueprint)
    # init BackgroundScheduler job
    scheduler = BackgroundScheduler()
    # in your case you could change seconds to hours
    scheduler.add_job(hello_job, trigger='interval', seconds=3)
    scheduler.start()

    try:
        # To keep the main thread alive
        return app
    except:
        # shutdown if app occurs except 
        scheduler.shutdown()

আশা করি এটা সাহায্য করবে :)

রেফ:

  1. https://github.com/agronholm/apscheduler/blob/master/example/schedulers/background.py

4
আমি নিশ্চিত যে রিটার্নের বিবৃতি কখনই ব্যতিক্রম বাড়াবে না
তমাস হেজেডাস

12

একটি সহজ সমাধানের জন্য, আপনি কোনও রুট যুক্ত করতে পারেন

@app.route("/cron/do_the_thing", methods=['POST'])
def do_the_thing():
    logging.info("Did the thing")
    return "OK", 200

তারপরে একটি ইউনিক্স ক্রোন জব যুক্ত করুন যা পর্যায়ক্রমে এই শেষ পয়েন্টে পোস্ট করে। উদাহরণস্বরূপ, এটি একবারে চালাতে, টার্মিনাল টাইপ করুন crontab -eএবং এই লাইনটি যুক্ত করুন:

* * * * * /opt/local/bin/curl -X POST https://YOUR_APP/cron/do_the_thing

(নোট করুন যে কার্ল করার পথটি সম্পূর্ণ হতে হবে, যখন কাজটি চালিত হয় তখন এটি আপনার পাঠ্যপথ পাবে না by আপনি আপনার সিস্টেমে কার্ল করার জন্য পুরো পথটি খুঁজে পেতে পারেন) which curl )

আমি এটি পছন্দ করি যে ম্যানুয়ালি এই কাজটি পরীক্ষা করা সহজ, এটির কোনও অতিরিক্ত নির্ভরতা নেই এবং এটিতে বিশেষ কিছু চলছে না তা বোঝা সহজ।

সুরক্ষা

যদি আপনি পাসওয়ার্ডটি আপনার ক্রোন জব সুরক্ষিত করতে চান pip install Flask-BasicAuthতবে আপনি পারবেন এবং তারপরে আপনার অ্যাপ্লিকেশন কনফিগারেশনে শংসাপত্রগুলি যুক্ত করতে পারেন :

app = Flask(__name__)
app.config['BASIC_AUTH_REALM'] = 'realm'
app.config['BASIC_AUTH_USERNAME'] = 'falken'
app.config['BASIC_AUTH_PASSWORD'] = 'joshua'

কাজের শেষ পয়েন্টটি পাসওয়ার্ডে রক্ষা করতে:

from flask_basicauth import BasicAuth
basic_auth = BasicAuth(app)

@app.route("/cron/do_the_thing", methods=['POST'])
@basic_auth.required
def do_the_thing():
    logging.info("Did the thing a bit more securely")
    return "OK", 200

তারপরে আপনার ক্রোন জব থেকে এটি কল করতে:

* * * * * /opt/local/bin/curl -X POST https://falken:joshua@YOUR_APP/cron/do_the_thing

4
তুমি খুব মেধাবী! সত্যিই কার্যকর টিপ।
শার্ল শেরিফ

6

আরেকটি বিকল্প হতে পারে ফ্লাস্ক-এপিএসচেডুলার ব্যবহার করা যা ফ্লাস্কের সাথে দুর্দান্তভাবে অভিনয় করে, যেমন:

  • ফ্লাস্ক কনফিগারেশন থেকে শিডিয়ুলার কনফিগারেশন লোড করুন,
  • ফ্লাস্ক কনফিগারেশন থেকে কাজের সংজ্ঞা লোড করে

এখানে আরও তথ্য:

https://pypi.python.org/pypi/Flask-APScheduler


4

চালানো-কাজের (অফার) নিয়ন্ত্রণ এবং প্যারামিটার সহ শিডিউল এবং মাল্টিপ্রসেসিং ব্যবহার করে একটি সম্পূর্ণ উদাহরণ, রিটার্ন কোডগুলি সরল করে দেওয়া হয় এবং অন্তর 10 সিসিতে সেট করা হয়, every(2).hour.do()2 ঘন্টার জন্য পরিবর্তিত হয় । তফসিলটি বেশ চিত্তাকর্ষক এটি প্রবাহিত হয় না এবং সময় নির্ধারণের সময় আমি কখনই এটি 100 মিমির বেশি বন্ধ দেখিনি। থ্রেডিংয়ের পরিবর্তে মাল্টিপ্রসেসিং ব্যবহার করা হচ্ছে কারণ এটির একটি সমাপ্তির পদ্ধতি রয়েছে।

#!/usr/bin/env python3

import schedule
import time
import datetime
import uuid

from flask import Flask, request
from multiprocessing import Process

app = Flask(__name__)
t = None
job_timer = None

def run_job(id):
    """ sample job with parameter """
    global job_timer
    print("timer job id={}".format(id))
    print("timer: {:.4f}sec".format(time.time() - job_timer))
    job_timer = time.time()

def run_schedule():
    """ infinite loop for schedule """
    global job_timer
    job_timer = time.time()
    while 1:
        schedule.run_pending()
        time.sleep(1)

@app.route('/timer/<string:status>')
def mytimer(status, nsec=10):
    global t, job_timer
    if status=='on' and not t:
        schedule.every(nsec).seconds.do(run_job, str(uuid.uuid4()))
        t = Process(target=run_schedule)
        t.start()
        return "timer on with interval:{}sec\n".format(nsec)
    elif status=='off' and t:
        if t:
            t.terminate()
            t = None
            schedule.clear()
        return "timer off\n"
    return "timer status not changed\n"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

আপনি কেবল জারি করে এটি পরীক্ষা করেন:

$ curl http://127.0.0.1:5000/timer/on
timer on with interval:10sec
$ curl http://127.0.0.1:5000/timer/on
timer status not changed
$ curl http://127.0.0.1:5000/timer/off
timer off
$ curl http://127.0.0.1:5000/timer/off
timer status not changed

প্রতি 10 সেকেন্ডে টাইমারটি এতে থাকে কনসোলে একটি টাইমার বার্তা জারি করবে:

127.0.0.1 - - [18/Sep/2018 21:20:14] "GET /timer/on HTTP/1.1" 200 -
timer job id=b64ed165-911f-4b47-beed-0d023ead0a33
timer: 10.0117sec
timer job id=b64ed165-911f-4b47-beed-0d023ead0a33
timer: 10.0102sec

মাল্টিপ্রসেসিংয়ে বিশেষজ্ঞ নন তবে আপনি যদি এটি ব্যবহার করেন তবে আপনি সম্ভবত আচারের ত্রুটি পাবেন।
প্যাট্রিক মুটুকু

@ পেট্রিকমুতুকু, কেবলমাত্র আমি ডিজিটাল সিরিয়ালাইজিং (কুকিজ, টেম্প ফাইলগুলি) দেখি সমস্যা হ'ল অ্যাসিঙ্ক এবং ওয়েবসকেট তবে গ্লাতুব / টেকনথ্রেটিজ / সংবাদদাতা দেখুন ফ্লাস্ক আপনার এপি নয় । অ্যাপাচি ডাব্লুএসজি-তে সহজ ফ্রন্ট্যান্ডের সাথে খালি বিশ্রামে ফ্লাস্ক ছাড়িয়েছে।
মর্টেনবি

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.