首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Python APScheduler - AsyncIOScheduler是如何工作的?

Python APScheduler - AsyncIOScheduler是如何工作的?
EN

Stack Overflow用户
提问于 2020-07-20 18:47:07
回答 3查看 13.7K关注 0票数 11

我很难理解AsyncIOScheduler是如何工作的,它是如何非阻塞的?

如果我的工作是执行阻塞函数,AsyncIOScheduler会阻塞吗?

如果我将AsyncIOSchedulerThreadPoolExecutor结合使用呢?这是如何工作的呢?我能等任务执行吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-07-29 16:03:43

因此,在APScheduler中有三个重要的组件:

  1. 调度者
  2. 遗嘱执行人
  3. 数据存储

对于这个问题,只有1和2是相关的。

调度程序只是根据作业的间隔设置来决定何时调用作业,在AsyncIOScheduler的情况下,它使用异步实现等待期的非阻塞。它运行在与主进程相同的进程和线程中。如果您的应用程序已经在异步循环上运行,这是非常有用的,因为它节省了运行新进程/线程的开销。

现在,当一个作业需要执行时,它是被调用的执行器,在AsyncIOScheduler的情况下,默认是使用AsyncIOExecutor,如果作业函数被签名为异步,它运行在与Scheduler相同的线程和进程中,否则它使用异步run_in_executor在线程池中运行它。

这就引出了最后一个问题,如果我们将AsyncIOSchedulerThreadPoolExecutor结合使用会发生什么?从技术上讲,这与使用带有非异步函数的默认执行器相同,它将在线程池中运行,但调度程序将保留在主线程中。

票数 9
EN

Stack Overflow用户

发布于 2020-07-29 15:24:57

利用一些网络资源,我找到了一些有用的事实。希望它能帮到你。

一个典型的APScheduler实例包含数十个作业,它们执行常规的Python函数。APScheduler实例可以调度的作业数量没有限制;它只取决于机器的实际负载。默认情况下,APScheduler将所有作业存储在内存中.如果您希望您的作业能够从进程重新启动中存活下来,并且从上次触发时一直保持触发状态,则可以将这些作业存储在数据库中,例如任何关系数据库管理系统、Redis、MongoDB等。

根据应用程序的运行方式,它可以作为线程或异步任务运行,也可以作为异步任务运行。初始化时,APScheduler不会执行任何操作,除非您将Python函数添加为作业。一旦添加了所有作业,就需要“启动”调度程序。关于如何使用APScheduler的一个简单示例,这里有一个代码片段,它只起作用。

代码语言:javascript
运行
复制
from urllib.request import urlopen
from apscheduler.schedulers.blocking import BlockingScheduler

scheduler = BlockingScheduler()

@scheduler.scheduled_job("interval", seconds=10)
def keep_warm():
    urlopen("https://enqueuezero.com", timeout=10)
    
scheduler.start()

这确保每10秒请求一个URL。该程序作为阻塞进程运行。如果您想将它们与应用程序共存,可以考虑使用BackgroundSchedulerAsyncIOScheduler等。

这里有一些用于BackgroundScheduler的代码片段。

代码语言:javascript
运行
复制
from datetime import datetime
import time
import os

from apscheduler.schedulers.background import BackgroundScheduler


def tick():
    print('Tick! The time is: %s' % datetime.now())


if __name__ == '__main__':
    scheduler = BackgroundScheduler()
    scheduler.add_job(tick, 'interval', seconds=3)
    scheduler.start()
    print('Press Ctrl+{0} to exit'.format('Break' if os.name == 'nt' else 'C'))

    try:
        # This is here to simulate application activity (which keeps the main thread alive).
        while True:
            time.sleep(2)
    except (KeyboardInterrupt, SystemExit):
        # Not strictly necessary if daemonic mode is enabled but should be done if possible
        scheduler.shutdown()

下面的代码将演示如何使用asyncio兼容的调度程序来调度以3秒钟间隔执行的作业。

代码语言:javascript
运行
复制
import asyncio
import os
from datetime import datetime

from apscheduler.schedulers.asyncio import AsyncIOScheduler


def tick():
    print('Tick! The time is: %s' % datetime.now())


if __name__ == '__main__':
    scheduler = AsyncIOScheduler()
    scheduler.add_job(tick, 'interval', seconds=3)
    scheduler.start()
    print('Press Ctrl+{0} to exit'.format('Break' if os.name == 'nt' else 'C'))

    # Execution will block here until Ctrl+C (Ctrl+Break on Windows) is pressed.
    try:
        asyncio.get_event_loop().run_forever()
    except (KeyboardInterrupt, SystemExit):
        pass

您可以使用此链接获得有关ap调度程序的更多示例!

票数 13
EN

Stack Overflow用户

发布于 2020-07-27 17:12:51

基于文档,在事件循环中执行AsyncIOScheduler。

它是非阻塞的,因为它只需将自己添加到事件循环中,并等待您启动它。

一旦事件循环启动,它将异步运行。

代码语言:javascript
运行
复制
from apscheduler.schedulers.asyncio import AsyncIOScheduler
import asyncio

async def job():
    print('hi')

scheduler = AsyncIOScheduler()
scheduler.add_job(job, "interval", seconds=3)

scheduler.start()

asyncio.get_event_loop().run_forever()

输出

代码语言:javascript
运行
复制
Run time of job "job (trigger: interval[0:00:03], next run at: 2020-07-27 14:06:39 -03)" was missed by 0:00:02.542515
hi
hi
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63001954

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档