云烟成雨 发表于 2024-6-17 19:48

关于python定时器的问题

apscheduler的同步定时任务,任务类型是date,按网上的说法,这个任务应该是指定日期执行一次就结束了,于是我设置了今天的日期,想在几点几分几秒时运行一次后结束,但程序并没有像我期望的那样,这个任务执行后,程序挂在那儿不动了,Ctrl+C都无法终止cmd,导致我最终还是手动加了个os退出
这个date的定时任务为什么执行后没有退出?求大佬解惑

代码如下
import pyautogui, os;
from datetime import datetime
from apscheduler.schedulers.blocking import BlockingScheduler
scheduler = BlockingScheduler(timezone='Asia/Shanghai')

def runGame():
    print('111')

nowYear = datetime.now().year; #获取年
nowMonth = datetime.now().month; #获取月
nowDay = datetime.now().day; #日

runTime = {
    'hour': 19,
    'minute': 41,
    'second': 0
}
print(f"等待执行 {str(runTime['hour'])}:{str(runTime['minute'])}:{str(runTime['second'])}")
scheduler.add_job(runGame, 'date', args=[], id='runGame',
    run_date=datetime(nowYear, nowMonth, nowDay, runTime['hour'], runTime['minute'], runTime['second']))
scheduler.start()
print('结束了')

zhzhx 发表于 2024-6-17 20:16

import pyautogui
import os
from datetime import datetime
from apscheduler.schedulers.background import BackgroundScheduler

def runGame():
    print('111')
    # 在这里可以添加关闭调度器的逻辑,但在这个例子中我们不需要

nowYear = datetime.now().year
nowMonth = datetime.now().month
nowDay = datetime.now().day

runTime = {
    'hour': 19,
    'minute': 41,
    'second': 0
}
print(f"等待执行 {runTime['hour']}:{runTime['minute']}:{runTime['second']}")

scheduler = BackgroundScheduler(timezone='Asia/Shanghai')
scheduler.add_job(runGame, 'date', run_date=datetime(nowYear, nowMonth, nowDay, runTime['hour'], runTime['minute'], runTime['second']))
scheduler.start()

# 由于我们使用了BackgroundScheduler,主线程不会被阻塞
# 所以我们可以直接等待任务执行完毕(如果有必要的话)
# 或者在这里添加其他逻辑,比如检查任务是否已经执行

# 示例:等待一段时间后检查任务是否执行并退出
import time
time.sleep(60)# 假设我们等待一分钟来检查任务是否执行
# 在这里可以添加逻辑来检查任务是否执行,但在这个例子中我们直接退出
print('程序结束')

ytfty 发表于 2024-6-17 21:10

设定几点几分这种情况思路是否正确? 通常是几点几分开始执行,如果未执行,等待多久重新执行,直到执行成功为止,不然你这个程序太柔弱了

FitContent 发表于 2024-6-18 00:34

本帖最后由 FitContent 于 2024-6-18 00:43 编辑

首先解释为什么没有退出:

1.   该库中有一个 `任务列表`,调用 `.add_job` 方法就会添加任务到里面。
2.   当调用 `.start` 方法时,它会阻塞主线程、并且以线程的方式执行被添加的任务。
3.   当 `任务列表` 为空时,**也就是没有任务执行的时候,它也没有退出主线程,而是等待新的任务被添加**。



---



而楼主期望的是:没有任务执行,那就赶紧给我结束程序呀。

解决方案:参考链接 (https://stackoverflow.com/questions/62257000/how-to-stop-blockscheduler-on-a-particular-end-date)

```python
scheduler = BlockingScheduler(timezone="Asia/Shanghai")


def runGame():
    print("111")
    scheduler.shutdown(wait=False)

```

# 简要说明

通过插入以下代码在开头部分,可以看到该库的日志输出:

```python
# 插入的代码,取自官方文档
import logging

logging.basicConfig()
logging.getLogger("apscheduler").setLevel(logging.DEBUG)
```



以下是日志输出,注释说明的部分用 `======` 标记,并且为了便于查看,插入了很多空行。

```txt
INFO:apscheduler.scheduler:Adding job tentatively -- it will be properly scheduled when the scheduler starts
INFO:apscheduler.scheduler:Added job "runGame" to job store "default"

INFO:apscheduler.scheduler:Scheduler started
DEBUG:apscheduler.scheduler:Looking for jobs to run

==========
这里从任务列表中找到了添加的任务 runGame,并且以线程的方式执行了它,然后从任务列表中将该任务删除了
==========
DEBUG:apscheduler.scheduler:Next wakeup is due at 2024-06-17 23:03:50+08:00 (in 22.816249 seconds)
DEBUG:apscheduler.scheduler:Looking for jobs to run
INFO:apscheduler.scheduler:Removed job runGame

==========
* * * 从这里可以看出,当没有任务时,程序并没有选择结束,而是等待新的任务被添加
==========
DEBUG:apscheduler.scheduler:No jobs; waiting until a job is added

=========
这里是 runGame 任务的执行信息
=========
INFO:apscheduler.executors.default:Running job "runGame (trigger: date, next run at: 2024-06-17 23:03:50 CST)" (scheduled at 2024-06-17 23:03:50+08:00)
111
INFO:apscheduler.executors.default:Job "runGame (trigger: date, next run at: 2024-06-17 23:03:50 CST)" executed successfully
```

suifenging 发表于 2024-6-18 08:49

一般写的程序都是要重复运行的啊,结束了多不好

auth98 发表于 2024-6-18 10:22

如果需要,可是使用(scheduler.shutdown(wait=False))停止定时任务的哦

云烟成雨 发表于 2024-6-18 11:18

FitContent 发表于 2024-6-18 00:34
首先解释为什么没有退出:

1.   该库中有一个 `任务列表`,调用 `.add_job` 方法就会添加任务到里面 ...

感谢大佬,分析很详细
页: [1]
查看完整版本: 关于python定时器的问题