0Pricing
Pandas & NumPy Academy · 课时

调度并记录 pipeline 运行

从命令行将 pipeline 作为 Python 脚本运行,记录开始和结束时间,并使用 cron 或调度器实现自动化。

调度并记录 pipeline 运行 是 CoddyKit 上的免费 Pandas & NumPy Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Pandas & NumPy Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Pandas & NumPy Academy 课程共包含 4 节课。

从笔记本到脚本

如果流水线只能在开发人员手动打开笔记本时运行,那么除了第一次运行外,它不会产生任何业务价值。要实现每日自动运行,流水线必须组织成一个可从命令行执行的 Python 脚本:python pipeline.py。这要求具备 if __name__ == '__main__': 入口、命令行参数解析和正确的日志记录——这是生产脚本的三大支柱。

# pipeline.py
import argparse
import logging
import pandas as pd

def main(config_path):
    logging.info(f'Starting pipeline with config: {config_path}')
    # ... run ETL steps ...
    logging.info('Pipeline complete.')

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--config', default='config.json')
    args = parser.parse_args()
    main(args.config)

配置 Python 日志记录

Python 内置的 logging 模块才是记录流水线日志的正确工具,而不是 print() 语句。请使用 logging.basicConfig() 同时配置控制台输出和文件输出。正常进度使用 INFO 级别,失败使用 ERROR 级别。基于文件的日志会在进程退出后保留,这对于调试无人监看的定时运行至关重要。

import logging
from datetime import date

log_file = f'pipeline_{date.today()}.log'

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s %(levelname)s %(message)s',
    handlers=[
        logging.FileHandler(log_file),
        logging.StreamHandler()
    ]
)

logging.info('Logger configured.')

记录流水线的开始与结束

始终记录流水线运行的开始时间、结束时间和耗时。这可以建立基准:如果流水线通常运行 45 秒,而今天耗时 8 分钟,就说明发生了变化——可能是输入文件大了 10 倍,也可能是数据库查询运行缓慢。带时间戳的开始和结束日志条目,让您仅通过日志文件就能轻松完成比较。

import time
import logging

def run_pipeline(config):
    start = time.time()
    logging.info(f'Pipeline START | env={config.get("env", "dev")} | input={config["input_path"]}')

    try:
        df = extract(config)
        df_clean = transform(df, config)
        load(df_clean, config)
        elapsed = time.time() - start
        logging.info(f'Pipeline SUCCESS | rows={len(df_clean)} | elapsed={elapsed:.1f}s')
    except Exception as e:
        logging.error(f'Pipeline FAILED | error={e}', exc_info=True)
        raise

记录每个步骤的行数

记录每个转换步骤进入和退出时的行数。一份清晰的日志如下所示:提取:50,000 行 → 删除空值:49,200 行 → 筛选:47,800 行 → 输出:47,800 行。通过这条追踪信息,可以立即看出每个步骤删除了多少行,以及这些数字是否符合预期。异常的行数减少会表现为日志计数中的明显断点。

def log_step(df, step_name):
    logging.info(f'{step_name}: {len(df):,} rows')
    return df

import pandas as pd

df = (pd.read_csv('orders.csv')
    .pipe(log_step, 'extract')
    .dropna(subset=['revenue'])
    .pipe(log_step, 'drop_nulls')
    .query('quantity > 0')
    .pipe(log_step, 'filter_qty')
)
print('Step logging complete.')

在 Linux/Mac 上使用 cron 调度

cron 是 Unix 系统用于重复运行任务的标准调度器。请使用 crontab -e 编辑 crontab,并添加一行来指定脚本的运行时间。格式为:分钟 小时 日期 月份 星期 命令。每天早上 6:00 运行的流水线可以使用 0 6 * * * /usr/bin/python /path/to/pipeline.py。cron 条目中始终应使用绝对路径,因为 cron 运行在精简环境中,不会加载 shell 的 PATH 设置。

# crontab entry — edit with: crontab -e
# Run pipeline.py at 06:00 every day
# 0 6 * * * /opt/homebrew/bin/python /Users/analyst/pipeline.py --config /Users/analyst/config.json >> /Users/analyst/cron.log 2>&1

# Common cron patterns:
# 0 6 * * *      — daily at 06:00
# 0 */4 * * *    — every 4 hours
# 0 9 * * 1      — every Monday at 09:00
print('Cron schedule format: minute hour day month weekday')

使用 Python schedule 库调度

schedule 库提供了一种纯 Python 方式,可以按指定时间间隔运行任务,而无需接触 cron。它适用于无法使用 cron 的环境(如 Windows),或您希望将调度逻辑直接放在 Python 进程中的情况。请将流水线封装在定时任务循环中,并保持进程运行,以便重复执行。

# pip install schedule
# import schedule, time

# def job():
#     logging.info('Scheduled run starting...')
#     run_pipeline(CONFIG)

# schedule.every().day.at('06:00').do(job)
# schedule.every(4).hours.do(job)

# while True:
#     schedule.run_pending()
#     time.sleep(60)

print('schedule library: use for in-process Python scheduling')

错误处理与退出代码

流水线脚本失败时应返回非零退出代码,以便调度器知道任务失败了。请将主执行逻辑放在 try/except 块中,并在失败时调用 sys.exit(1)。cron、Jenkins 和 Airflow 都会检查退出代码:非零代码会触发警报、重新运行或通知。如果未处理的异常没有设置退出代码,自动监控可能完全不会察觉。

import sys

def main():
    try:
        run_pipeline(CONFIG)
        sys.exit(0)  # success
    except AssertionError as e:
        logging.error(f'Data validation failed: {e}')
        sys.exit(2)  # data error
    except Exception as e:
        logging.error(f'Unexpected error: {e}', exc_info=True)
        sys.exit(1)  # general failure

print('Exit code 0=success, 1=error, 2=data failure')

编写流水线运行摘要文件

成功运行后,请在输出文件旁写入一个小型 JSON 摘要文件。摘要中应包含运行时间戳、输入行数、输出行数、删除的行数以及耗时。监控系统和仪表板可以读取此文件,跟踪流水线健康状况随时间的变化。显示过去 30 天的输出行数的仪表板,可以轻松发现数据源开始提供更少记录的日期。

import json
from datetime import datetime

def write_run_summary(config, input_rows, output_rows, elapsed):
    summary = {
        'run_at': datetime.now().isoformat(),
        'input_path': config['input_path'],
        'input_rows': input_rows,
        'output_rows': output_rows,
        'rows_dropped': input_rows - output_rows,
        'elapsed_seconds': round(elapsed, 2),
        'status': 'success'
    }
    with open('last_run_summary.json', 'w') as f:
        json.dump(summary, f, indent=2)
    print('Run summary written.')

幂等调度:避免重复运行

如果定时流水线意外触发两次,就不应破坏输出。请将加载步骤设计为幂等的:使用带日期的输出文件名,或用最新结果覆盖同一个输出文件。对于数据库加载,请使用 if_exists='replace' 或 UPSERT 模式。切勿在没有去重步骤的情况下使用 append 模式,否则每次定时运行都会向输出表添加重复行。

from datetime import date

def load_idempotent(df, config):
    # Date-stamped output: each run overwrites its own day's file
    output_path = f"output_{date.today().strftime('%Y%m%d')}.parquet"
    df.to_parquet(output_path, index=False)
    logging.info(f'Loaded {len(df)} rows to {output_path}')

管道失败告警

对于业务运营所依赖的管道,失败后没有任何提示是很危险的。请设置一个简单的告警:如果运行摘要文件未在预期时间窗口内更新,就发送电子邮件或 Slack 消息。Python 的 smtplib 可以在失败时发送电子邮件,您也可以使用 Webhook 向 Slack 发布消息。在退出代码为 1 或 2 时立即发出告警,这样分析师就能在业务人员发现之前知道当天的数据刷新已经失败。

import smtplib

def send_failure_alert(error_msg):
    # Example: send plain-text email via SMTP
    # server = smtplib.SMTP('smtp.example.com', 587)
    # server.sendmail('pipeline@company.com',
    #                 'analyst@company.com',
    #                 f'Subject: Pipeline Failed\n\n{error_msg}')
    # server.quit()
    print(f'[ALERT] Would send failure notification: {error_msg}')

# In main():
# except Exception as e:
#     send_failure_alert(str(e))
#     sys.exit(1)
print('Alert integration pattern shown above.')

完整的定时管道脚本

将所有部分——参数解析、日志配置、运行摘要、错误处理和退出代码——组合成一个完整的管道脚本。这个脚本可以直接放入任何环境,指定一个配置文件,并通过 cron 或任何工作流编排器进行调度。每次执行时,它都会生成带日期的日志文件、运行摘要和带日期的输出文件,使每次运行都具备完整的审计能力,并且可以独立复现。

# Full script skeleton:
# 1. parse --config argument
# 2. configure logging to file + console
# 3. load JSON config
# 4. validate config
# 5. run extract() -> transform() -> load()
# 6. write run summary JSON
# 7. sys.exit(0) on success, sys.exit(1) on failure

print('Production pipeline script structure complete.')
print('Schedule with: crontab -e  or  python scheduler.py')

快速检查

测试您对本课数据分析概念的理解。

课程回顾

在本课中,您学习了:将管道构造成带有参数解析和日志记录的命令行脚本、使用 cron 进行调度,并通过非零退出代码和告警处理失败,以及编写运行摘要文件并设计幂等的加载步骤,以实现可靠的自动化执行。恭喜您完成“数据分析:Pandas 与 NumPy”学习路线!

常见问题解答

「调度并记录 pipeline 运行」课时是免费的吗?

是的 — 「调度并记录 pipeline 运行」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Pandas & NumPy Academy 课程的其余内容,请升级到 CoddyKit PRO。 Pandas & NumPy Academy 课程共包含 4 节课。

「调度并记录 pipeline 运行」这节课中我会学到什么?

从命令行将 pipeline 作为 Python 脚本运行,记录开始和结束时间,并使用 cron 或调度器实现自动化。 你通过在浏览器中直接运行的动手代码来练习 Pandas & NumPy Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Pandas & NumPy Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Pandas & NumPy Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「调度并记录 pipeline 运行」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Pandas & NumPy Academy 课中编写并运行代码吗?

能。每节 Pandas & NumPy Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 将转换步骤组织为函数
  2. 使用配置字典参数化 pipeline
  3. 使用断言测试 pipeline 步骤
  4. 调度并记录 pipeline 运行
← 返回 Pandas & NumPy Academy