网站全屏图片怎么做,怎么做有声小说网站播音员,苏州万户网络科技有限公司,大庆网站建设公司哪家好背景#xff1a;工作使用python django apscheduler celery MySQL redis#xff0c;某次想要使用异步的结果资料不全#xff0c;所以想要搞一搞#xff0c;问题是中文译本也不太好#xff0c;为了提升熟练度#xff0c;自己也来一套
时间#xff1a;20240822
目的…背景工作使用python django apscheduler celery MySQL redis某次想要使用异步的结果资料不全所以想要搞一搞问题是中文译本也不太好为了提升熟练度自己也来一套
时间20240822
目的后期会不定更新其内容增加示例
原文网址https://apscheduler.readthedocs.io/en/3.x/userguide.html
用户指南
安装 APScheduler
推荐的安装方法是使用pip
pip install apscheduler
如果你的pip尚未安装你可以轻松安装它通过下载并运行 get-pip.py
如果因为某些原因pip无法工作未安装或安装后无法执行你可以从pypi网站手动下载APScheduler模块解压提取后安装它
python setup.py install 代码示例
源代码中包含了示例文件夹在这个文件夹中你可以找到很多以不同方式使用APscheduler的工作示例。这些例子你也可以在网上浏览地址为APscheduler 使用示例
基础概念
APscheduler有四种组件 triggers -- 触发器 job stores -- 作业存储器 executors -- 执行器 schedulers -- 调度器
触发器包含调度逻辑每一个任务原文为job此处译为任务有它自己的触发器触发器决定了任务下次运行的时间。除了初始配置触发器是完全无状态的
作业存储器存放了需要调度的任务默认的作业存储器仅是简单的保存在内存中其他的作业存储器是各种各样的数据库。任务数据被持久化保存时需要序列化当加载回来时需要被反序列化。作业存储器除默认的以外不会将数据保存在内存中而是作为中间人在后端实现保存更新加载搜索任务。作业存储器绝不能再多个调度器间共享。
执行器的作用是处理运行中的任务他们通常通过将指定的可调用对象作为一个任务提交给线程池或进程池来完成这项操作。工作完成后执行器通知调度器然后调度器发出适当的事件信号。
调度器通常将其他部分捆绑在一起。在应用程序中通常只有一个调度器。应用程序开发人员通常不直接处理任务存储、执行器或触发器。相反调度器提供了适当的接口来处理所有这些。配置任务存储器和执行器是通过调度器完成的添加、修改和删除任务也是如此。
选择正确的调度器
调度器的选择主要取决于编程环境和使用APScheduler的目的。以下是选择调度器的快速指南
BlockingScheduler在调度器是进程中唯一运行的内容时使用BackgroundScheduler不使用以下任何框架并希望调度器在应用程序内部后台运行时使用AsyncIOScheduler如果应用程序使用asyncio模块请使用GeventScheduler如果应用程序使用gevent请使用TornadoScheduler如果正在构建Tornado应用程序请使用TwistedScheduler如果正在构建Twisted应用程序请使用QtScheduler如果正在构建Qt应用程序请使用
足够简单吗
选择正确的作业存储器
要选择合适的任务存储器需要确定是否需要任务持久性。如果在应用程序开始时总是重新创建任务那么可以使用默认的MemoryJobStore如果需要任务在调度器重启或应用程序崩溃中持续存在那么选择通常归结于编程环境中使用的工具。当然如果可以自由选择推荐选择使用PostgreSQL后端的SQLAlchemyJobStore因为它有强大的数据完整性保护。
选择正确的执行器
同样如果使用上述框架之一通常会自动选择执行器。否则默认的ThreadPoolExecutor应该足够满足大多数需求。如果工作负载涉及CPU密集型操作应该考虑使用ProcessPoolExecutor来利用多个CPU核心。甚至可以同时使用两者将进程池执行器添加为辅助执行器。
选择正确的触发器
当计划一个任务时需要为其选择一个触发器。触发器决定了任务运行日期/时间的逻辑。APScheduler自带三种内置触发器类型
date当您希望在某个特定时间点仅运行一次任务时使用。
interval当您希望以固定的时间间隔运行任务时使用。
cron当您希望在一天中的某个些特定时间定期运行任务时使用。
还可以将多个触发器组合成一个这样当所有参与的触发器都同意的时间或者任何一个触发器会触发时它就会触发。有关组合触发器的更多信息请参阅相关文档。也可以在各自的API文档页面上找到每个任务存储、执行器和触发器类型的插件名称。
配置调度器
APScheduler 提供了许多不同的方式来配置调度器。您可以使用配置字典或者以关键字参数的形式传入选项。您还可以先实例化调度器添加任务然后再配置调度器。这样您可以在任何环境中获得最大的灵活性。
完整的调度器级别配置选项列表可以在 BaseScheduler 类的 API 参考中找到。调度器子类也可能有额外的选项这些选项在它们各自的 API 参考中有文档说明。各个任务存储和执行器的配置选项也可以在它们的 API 参考页面上找到。
假设您想在应用程序中使用默认的任务存储和默认的执行器运行 BackgroundScheduler
from apscheduler.schedulers.background import BackgroundSchedulerscheduler BackgroundScheduler()# Initialize the rest of the application here, or before the scheduler initialization
这将配置一个带有名为“default”的MemoryJobStore和名为“default”的ThreadPoolExecutor默认最大线程数为10的BackgroundScheduler。
现在假设想要更多。希望使用两个执行器拥有两个任务存储并且还想调整新任务的默认值并设置不同的时区。以下三个示例完全等效将提供
一个名为“mongo”的MongoDBJobStore
一个名为“default”使用SQLite的SQLAlchemyJobStore
一个名为“default”的ThreadPoolExecutor工作线程数为20
一个名为“processpool”的ProcessPoolExecutor工作线程数为5
调度器的时区设置为UTC
默认情况下关闭新任务的合并
新任务的默认最大实例限制为3
方法1
from pytz import utcfrom apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.jobstores.mongodb import MongoDBJobStore
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from apscheduler.executors.pool import ThreadPoolExecutor, ProcessPoolExecutorjobstores {mongo: MongoDBJobStore(),default: SQLAlchemyJobStore(urlsqlite:///jobs.sqlite)
}
executors {default: ThreadPoolExecutor(20),processpool: ProcessPoolExecutor(5)
}
job_defaults {coalesce: False,max_instances: 3
}
scheduler BackgroundScheduler(jobstoresjobstores, executorsexecutors, job_defaultsjob_defaults, timezoneutc)
方法2
from apscheduler.schedulers.background import BackgroundScheduler# The apscheduler. prefix is hard coded
scheduler BackgroundScheduler({apscheduler.jobstores.mongo: {type: mongodb},apscheduler.jobstores.default: {type: sqlalchemy,url: sqlite:///jobs.sqlite},apscheduler.executors.default: {class: apscheduler.executors.pool:ThreadPoolExecutor,max_workers: 20},apscheduler.executors.processpool: {type: processpool,max_workers: 5},apscheduler.job_defaults.coalesce: false,apscheduler.job_defaults.max_instances: 3,apscheduler.timezone: UTC,
})
方法3
from pytz import utcfrom apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from apscheduler.executors.pool import ProcessPoolExecutorjobstores {mongo: {type: mongodb},default: SQLAlchemyJobStore(urlsqlite:///jobs.sqlite)
}
executors {default: {type: threadpool, max_workers: 20},processpool: ProcessPoolExecutor(max_workers5)
}
job_defaults {coalesce: False,max_instances: 3
}
scheduler BackgroundScheduler()# .. do something else here, maybe add jobs etc.scheduler.configure(jobstoresjobstores, executorsexecutors, job_defaultsjob_defaults, timezoneutc)
启动调度器
启动调度器只需在调度器上简单地调用start()方法。对于BlockingScheduler之外的其他调度器此调用将立即返回您可以继续应用程序的初始化过程可能会向调度器添加任务。
对于BlockingScheduler您只想在完成任何初始化步骤后才调用start()。
注意调度器启动后您将无法再更改其设置。
添加任务
将任务添加到调度器有两种方式
1.通过调用add_job()方法
2.通过使用scheduled_job()装饰器修饰一个函数
第一种方式是最常见的做法。第二种方式主要用于声明在应用程序运行时不会更改的任务。add_job()方法返回一个apscheduler.job.Job实例您可以稍后使用它来修改或删除任务。
您可以随时在调度器上安排任务。如果添加任务时调度器尚未运行则该任务将被暂时安排并且只有在调度器启动时才会计算其首次运行时间。
重要的是要注意如果您使用序列化任务的执行器或任务存储它会对您的任务增加一些要求
1. 目标可调用对象必须是全局可访问的
2. 可调用对象的任何参数必须是可序列化的
在内置的任务存储中只有MemoryJobStore不序列化任务。在内置的执行器中只有ProcessPoolExecutor会序列化任务。
重要
如果在应用程序初始化期间在持久性任务存储中安排任务您必须为任务定义一个明确的ID并使用replace_existingTrue否则每次应用程序重启时都会得到任务的一个新副本
提示
要立即运行作业请在添加作业时省略参数。
移除任务
当从调度器中删除一个任务时它会从其关联的任务存储中被移除并且不会再被执行。有两种方法可以实现这一点
1、通过使用任务的ID和任务存储别名调用remove_job()
2、通过对从add_job()获得的Job实例调用remove()
后一种方法可能更方便但它要求您在添加任务时保存收到的Job实例。对于通过scheduled_job()安排的任务第一种方法是唯一的方法。
如果任务的计划结束即其触发器不再产生任何进一步的运行时间它会自动被移除。
示例
job scheduler.add_job(myfunc, interval, minutes2)
job.remove()
同样使用明确的任务id
scheduler.add_job(myfunc, interval, minutes2, idmy_job_id)
scheduler.remove_job(my_job_id)
暂停和恢复任务
可以通过Job实例或调度器本身容易的暂停和恢复任务。当一个任务被暂停时其下一次运行时间会被清除并且在任务恢复之前不会为其计算任何进一步的运行时间。要暂停一个任务使用以下任一方法
apscheduler.job.Job.pause()
apscheduler.schedulers.base.BaseScheduler.pause_job()
要恢复任务
apscheduler.job.Job.resume()
apscheduler.schedulers.base.BaseScheduler.resume_job()
获取任务列表
要获取计划任务的机器可处理列表可以使用get_jobs()方法。它将返回Job实例的列表。如果只对特定任务存储中的任务感兴趣则可以在第二个参数中给出任务存储别名。
为了方便起见您可以使用print_jobs()方法它会打印出任务、触发器和下一次运行时间的格式化列表。
修改任务
您可以通过调用apscheduler.job.Job.modify()或modify_job()来修改任何任务属性。您可以修改除id之外的任何Job属性。
示例
job.modify(max_instances6, nameAlternate name)
如果想重新安排任务——即更改其触发器可以使用apscheduler.job.Job.reschedule()或reschedule_job()。这些方法为任务构造一个新的触发器并根据新触发器重新计算其下一次运行时间。
示例
scheduler.reschedule_job(my_job_id, triggercron, minute*/5)
关闭调度器
关闭调度器示例
scheduler.shutdown()
默认情况下调度器会关闭其作业存储器和执行器并等待直到所有当前执行作业已完成。如果您不想等待可以执行以下操作
scheduler.shutdown(waitFalse)
关闭作业存储和执行程序但不会等待任何运行 要完成的任务
暂停和恢复调度器
暂停调度器是可以实现的
scheduler.pause()
这将导致调度器在进程恢复之前无法唤醒
scheduler.resume()
也可以在暂停状态下启动调度器即不进行第一次唤醒调用
scheduler.start(pausedTrue)
这在你需要在不希望的任务运行之前将其修剪掉时非常有用。
限制同时执行的任务实例数量
默认情况下每个任务只允许同时运行一个实例。这意味着如果任务即将运行但前一次运行尚未完成那么最近一次运行将被视为误触发。可以通过在添加任务时使用max_instances关键字参数来设置调度器允许特定任务同时运行的最大实例数。
错过作业执行和合并
有时调度器可能无法在计划的时间执行预定的任务。最常见的情况是当任务被安排在持久性任务存储中并且在任务应该执行后调度器被关闭并重新启动时。当这种情况发生时该任务被认为是“误触发”。然后调度器将检查每个错过的执行时间与任务的misfire_grace_time选项可以在每个任务的基础上设置或在调度器中全局设置以查看是否仍应触发执行。这可能导致任务连续执行几次。
如果这种行为对你的特定用例不可取可以使用合并将所有错过的执行合并为一次。换句话说如果为任务启用了合并并且调度器看到一个或多个排队的执行它将只触发一次。对于“绕过”的运行不会发送任何误触发事件。
注意
如果由于线程池中没有可用的线程或进程而导致任务执行延迟执行器可能会因为运行太晚与最初指定的运行时间相比而跳过它。如果您的应用程序中可能发生这种情况您可能希望增加执行器中的线程/进程数量或者将misfire_grace_time设置调整为更高的值。
执行器事件
可以为调度器附加事件监听器。调度器事件在某些情况下会被触发并且可能会携带有关该特定事件的详细信息。通过将适当的掩码参数传递给add_listener()并使用OR将不同的常量组合在一起可以仅侦听特定类型的事件。监听器可调用的参数是一个即事件对象。
有关可用事件及其属性的详细信息请参阅事件模块的文档。
示例
def my_listener(event):if event.exception:print(The job crashed :()else:print(The job worked :))scheduler.add_listener(my_listener, EVENT_JOB_EXECUTED | EVENT_JOB_ERROR)
故障排除
如果调度器没有按预期工作将apscheduler日志记录器的日志级别提高到DEBUG级别会很有帮助。
如果您还没有启用日志记录可以这样做
import logginglogging.basicConfig()
logging.getLogger(apscheduler).setLevel(logging.DEBUG)
这将提供大量有关调度器内部发生的情况的有用信息。
还要确保检查常见问题解答部分以查看您的问题是否已有解决方案。 初版完成