如何部署Python Worker到Heroku且避免推送后自动运行?
解决方案说明
问题根源
Heroku 在部署代码时会自动启动 Procfile 中定义的所有 dyno,你的 worker: python main.py 配置会让 worker dyno 启动后立即执行 main.py,这就是每次推送代码时脚本自动运行的原因。
可行的解决方法
方法1:用 Heroku Scheduler 直接触发任务,关闭持久化 worker dyno
- 操作步骤:
- 部署代码后,执行命令将 worker dyno 缩容到0:
也可以在 Heroku 控制台的应用设置中配置默认 worker 数量为0,避免每次部署后手动操作。heroku ps:scale worker=0 - 在 Heroku Scheduler 中设置每日任务,直接运行命令:
python main.py
- 部署代码后,执行命令将 worker dyno 缩容到0:
- 优势:无需修改脚本,仅通过配置即可解决问题,且仅在任务触发时占用 dyno 资源,成本更低。
方法2:修改脚本,仅在调度触发时执行核心逻辑
- 修改脚本:在
main.py中添加环境变量检查,只有特定变量存在时才运行核心代码:import os def main(): # 原有的脚本逻辑 pass if __name__ == "__main__": # 仅当环境变量 RUN_FROM_SCHEDULER 为 true 时执行 if os.getenv("RUN_FROM_SCHEDULER") == "true": main() else: print("非调度触发,退出脚本") - 配置调度器:在 Heroku Scheduler 中设置任务命令为:
RUN_FROM_SCHEDULER=true python main.py - 优势:保留 worker dyno 配置,但部署时脚本不会执行核心逻辑,仅在调度触发时运行。
方法3:使用 APScheduler 内置调度(可行,需修改脚本)
- 修改脚本:将调度逻辑集成到脚本中,让 worker dyno 持续运行并等待调度触发:
from apscheduler.schedulers.blocking import BlockingScheduler import datetime def job(): # 原有的脚本逻辑 print(f"执行任务:{datetime.datetime.now()}") if __name__ == "__main__": scheduler = BlockingScheduler() # 配置每天特定时间运行(示例为 UTC 时间3点) scheduler.add_job(job, 'cron', hour=3, minute=0) print("调度器已启动,等待下一次任务执行...") scheduler.start() - 注意事项:此方法需要 worker dyno 24小时持续运行,会占用更多 dyno 时长,成本高于 Heroku Scheduler,适合需要复杂调度规则(如多时段、间隔执行)的场景。
内容的提问来源于stack exchange,提问作者smaica
相关产品推荐
相关产品推荐

