page contents

Python定时任务踩坑记录,schedule和cron到底用哪个好

爬起来一看,线上数据采集脚本挂了。原因很离谱——服务重启之后,我用 schedule 库写的定时任务没跟着自动拉起来,整整漏了6个小时的数据。

attachments-2026-06-TcZOT21P6a3c8b6111d2b.png你是不是有这样的场景:半夜两点被一条报警短信炸醒了。

爬起来一看,线上数据采集脚本挂了。原因很离谱——服务重启之后,我用 schedule 库写的定时任务没跟着自动拉起来,整整漏了6个小时的数据。

这事儿说白了就是自己挖的坑。趁着记忆还热乎,把这两年用Python做定时任务踩过的坑都捋一遍,也顺便聊聊 schedule 和 cron 这俩老冤家,到底该怎么选。

 

先说schedule,确实香

刚接触定时任务那会儿,我一眼就相中了 schedule。为啥?因为它真的太简单了:

importschedule
importtime

defsync_data():
    print("开始同步数据...")
    # 你的业务逻辑

schedule.every(10).minutes.do(sync_data)
schedule.every().day.at("02:00").do(sync_data)

whileTrue:
    schedule.run_pending()
    time.sleep(1)

看到没?几行核心代码,一个定时任务就跑起来了。不用学什么cron表达式,不用碰Linux系统配置,pip install schedule 装完就能用。

那段时间我跟人安利schedule都是这么说的:“兄弟,别搞那些花里胡哨的,schedule一把梭就完了。”

直到被现实反复教育。

schedule的坑,我是真踩了不少

进程一挂,任务全没

这个最致命。schedule的任务列表是存在内存里的,进程一死,所有调度规则灰飞烟灭。

你可能想,写个 systemd 或者 supervisor 把进程拉起来不就行了?太天真了。进程重启之后,schedule不会记得上次任务执行到哪了,也不会帮你把漏掉的任务补回来。

我就遇到过一次,周五晚上服务OOM被系统杀了,周一早上才有人发现,中间两天的数据全是空的。老板问我怎么回事,我总不能说“Python的定时任务太脆弱了”吧……

阻塞起来要命

schedule默认是单线程串行执行的。假设你有两个任务,A每隔5分钟跑一次,B每小时跑一次。A里面有个慢查询,某次跑了8分钟,那B就得等着,活生生被拖延。

importschedule
importtime

defslow_task():
    print("慢任务开始...")
    time.sleep(500)  # 模拟一个耗时操作
    print("慢任务结束")

defquick_task():
    print("快任务执行了!")

schedule.every(5).minutes.do(slow_task)
schedule.every(10).minutes.do(quick_task)

whileTrue:
    schedule.run_pending()
    time.sleep(1)

跑起来你会发现 quick_task 经常迟到,因为它得等 slow_task 跑完才能轮到它。

官方文档倒是说了可以用多线程来绕:

importthreading

defrun_threaded(job_func):
    job_thread = threading.Thread(target=job_func)
    job_thread.start()

schedule.every(10).minutes.do(run_threaded, slow_task)

但你不觉得这已经开始变味了吗?本来图它简单,现在得自己管线程……那我还不如直接用更专业的工具呢。

啥都没有

schedule本质上就是一个“到点了就调函数”的小工具。它不管任务执没执行成功,不管日志写到哪,也不管出了异常要不要重试。你在生产环境用,出了问题全靠自己的 print 和 try-except 去排查。

这就好比你开着一辆没有仪表盘的车上高速——跑是能跑,但你永远不知道油还剩多少。

转投cron阵营

被schedule坑了几次之后,我把目光转向了cron。

这里说的“cron”不是某个Python库,而是Linux系统自带的 crontab 定时任务。这玩意儿从1975年就有了,比你我都老,真正的久经考验。

用法也很直白:

# 编辑当前用户的crontab
crontab -e

# 每10分钟执行一次Python脚本
*/10 * * * * /usr/bin/python3 /home/user/scripts/sync_data.py

# 每天凌晨2点执行
02 * * * /usr/bin/python3 /home/user/scripts/daily_report.py

写完保存就生效了,不用写 while True 循环,不用操心进程挂不挂,系统级的 crond 守护进程帮你管着呢。

当时我就想,这多好,稳如老狗。

然后我又被教育了。

cron的坑也不少,只是坑法不一样

环境变量——永远的经典

cron踩坑界的扛把子,没有之一。

你在终端里手动跑得好好的脚本,丢到crontab里就是不work。十有八九是环境变量的锅。因为cron执行命令时用的是一个极简环境,PATH只有 /usr/bin:/bin,你装的那些pip包、conda环境、自定义变量,它一概不认。

这个问题我至少踩过三次,每次都是“不应该啊”→ 排查半小时 → “又是环境变量”。

解决方案倒是不复杂:

# 方法1:在crontab头部声明PATH
PATH=/usr/local/bin:/usr/bin:/bin:/home/user/.local/bin
*/10 * * * * python3 /home/user/scripts/sync_data.py

# 方法2:用绝对路径(我最推荐这个)
*/10 * * * * /home/user/venv/bin/python /home/user/scripts/sync_data.py

# 方法3:source一下环境
*/10 * * * * source /home/user/.bashrc && python3 /home/user/scripts/sync_data.py

方法2最省心,也最不容易出幺蛾子。别问我是怎么知道的。

工作目录跟你以为的不一样

cron执行脚本时,工作目录默认是用户的home目录,不是脚本所在的目录。

如果你脚本里用了相对路径读文件:

# sync_data.py
withopen("config.json") asf:  # cron环境下这个路径是错的
    config = json.load(f)

终端里跑没问题,一放到cron里就报 FileNotFoundError,你说气不气。

解决办法很简单,脚本开头加一行:

importos
os.chdir(os.path.dirname(os.path.abspath(__file__)))

或者直接在crontab里先cd过去:

*/10 * * * * cd /home/user/scripts && python3 sync_data.py

日志去哪了?

cron默认会把输出发到系统邮件里,对,就是那个没人看的 /var/mail/ 目录。你要是没做重定向,出了bug都不知道去哪找。

所以请一定记住加日志重定向,这是铁律:

*/10 * * * * python3 /home/user/scripts/sync_data.py >> /home/user/logs/sync.log 2>&1

2>&1 是把错误输出也写到同一个文件里。别嫌麻烦,等你半夜排查问题的时候,你会感谢当时的自己。

时区问题,玄学中的玄学

cron用的时区取决于系统设置,而你服务器的时区可能跟你以为的不一样。

我碰过一次,服务器是UTC,我以为配的是北京时间凌晨2点,结果实际上是北京时间上午10点执行的。数据分析那边一看报表数据对不上,又是一通排查。这种问题特别难定位,因为你压根不会第一时间怀疑时区。

# 先检查系统时区
timedatectl

# 在crontab里声明时区(部分系统支持)
CRON_TZ=Asia/Shanghai
02 * * * python3 /home/user/scripts/daily_report.py

到底怎么选?

说了这么多,我自己的原则很简单——

schedule只用在临时脚本上。本地开发、数据验证、写个一次性脚本跑跑测试。比如你临时写个脚本每隔10分钟去某个API拉一下数据做调试,schedule绝对是最快的方案,没得说。但用完就扔,别惦记着让它上生产。

cron才是要上线的东西。线上服务、生产环境、任何你不想半夜被叫起来修的任务。cron虽然配置麻烦一点,但它稳定可靠有系统级别的保障,是真正的“设了就忘”。

如果你还需要更复杂的功能,比如任务依赖、分布式调度、Web管理界面之类的,可以看看 APScheduler 或者 Celery Beat,不过那就是另一个故事了,以后有机会再聊。

更多相关技术内容咨询欢迎前往并持续关注好学星城论坛了解详情。

想高效系统的学习Python编程语言,推荐大家关注一个微信公众号:Python编程学习圈。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Python入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。

attachments-2022-05-rLS4AIF8628ee5f3b7e12.jpg

 

  • 发表于 2026-06-25 09:59
  • 阅读 ( 24 )
  • 分类:Python开发

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
Pack
Pack

2179 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 2228 文章
  3. Pack 2179 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章