You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Cron仅在Python包执行路径相关代码变更时触发执行

解决Python包夜间Cron任务仅在执行路径变更时运行的方案

一、先明确__main__入口的实际执行依赖

要精准判断变更是否影响执行,首先得搞清楚入口运行时到底用到了哪些文件和函数——动态追踪是最靠谱的方式,能避免静态分析的误判:

  • 写个简单的追踪脚本,运行入口并记录所有被执行到的自有包文件/函数:
    import sys
    
    executed_files = set()
    executed_funcs = set()
    
    def trace_execution(frame, event, arg):
        if event == 'call':
            file_path = frame.f_code.co_filename
            # 只追踪自己包内的代码,过滤标准库和第三方依赖
            if 'your_package' in file_path and file_path.endswith('.py'):
                executed_files.add(file_path)
                func_name = frame.f_code.co_name
                executed_funcs.add(f"{file_path}:{func_name}")
        return trace_execution
    
    sys.settrace(trace_execution)
    
    # 运行你的包入口(根据实际入口逻辑调整)
    from your_package.__main__ import main
    main()
    
    # 保存结果到文件,供后续对比用
    with open('executed_files.txt', 'w') as f:
        f.write('\n'.join(executed_files))
    with open('executed_funcs.txt', 'w') as f:
        f.write('\n'.join(executed_funcs))
    
    替换your_package为你的包名,运行一次这个脚本就能拿到执行路径的基准数据。

二、用Git对比两次提交的变更

Cron任务每次运行时,先读取上一次执行时的Git哈希(存在last_commit.txt里),再对比当前HEAD的哈希,提取变更内容:

  • 用Shell脚本实现对比逻辑:
    # 读取上次运行的提交哈希,首次运行时用初始提交哈希
    LAST_COMMIT=$(cat last_commit.txt 2>/dev/null || echo "初始提交哈希")
    CURRENT_COMMIT=$(git rev-parse HEAD)
    
    # 获取两次提交之间变更的自有包Python文件
    CHANGED_FILES=$(git diff --name-only $LAST_COMMIT $CURRENT_COMMIT | grep "your_package.*\.py$")
    
    # 如果需要细粒度到函数,获取变更涉及的函数
    CHANGED_FUNCS=$(git diff -p $LAST_COMMIT $CURRENT_COMMIT | awk '
        /^diff --git/ {file=$3}
        /^def / {print file ":" substr($2, 1, index($2, "(")-1)}
    ' | grep "your_package")
    

三、判断是否需要执行包

根据对比结果,判断变更是否落在执行路径内:

文件级判断(简单场景)

如果变更的文件在executed_files.txt里,就执行包:

NEED_RUN=0
# 遍历变更文件,检查是否在执行路径中
for file in $CHANGED_FILES; do
  ABS_FILE=$(realpath "$file")
  if grep -q "^$ABS_FILE$" executed_files.txt; then
      NEED_RUN=1
      break
  fi
done

函数级判断(精准场景)

如果要排除“文件变更但仅修改未调用函数”的情况,就检查变更函数是否在executed_funcs.txt里:

NEED_RUN=0
for func in $CHANGED_FUNCS; do
  if grep -q "^$func$" executed_funcs.txt; then
      NEED_RUN=1
      break
  fi
done
# 额外处理新增文件的情况(新增文件如果被入口调用,也需要执行)
for file in $CHANGED_FILES; do
  if ! grep -q "^$(realpath "$file")$" executed_files.txt; then
      # 检查新增文件是否被入口依赖(可以用静态分析或临时运行验证)
      python -c "import your_package.__main__; import $(echo $file | sed 's/\.py$//' | tr '/' '.')" && NEED_RUN=1
      break
  fi
done

四、执行逻辑与Cron整合

最后在脚本里加入执行逻辑,并配置Cron:

if [ $NEED_RUN -eq 1 ]; then
  echo "Detected changes in execution path, running package..."
  python -m your_package.__main__
  # 更新上次运行的提交哈希
  echo $CURRENT_COMMIT > last_commit.txt
else
  echo "No relevant changes, skipping run."
fi

把脚本保存为run_on_change.sh,然后添加Cron任务:

crontab -e
# 每天凌晨2点执行,输出日志到指定文件
0 2 * * * /bin/bash /path/to/run_on_change.sh >> /path/to/cron_log.txt 2>&1

内容的提问来源于stack exchange,提问作者Harry Stuart

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 03:35:44