0

0

Flask应用中定时刷新CSV数据的高效策略

聖光之護

聖光之護

发布时间:2025-08-24 23:30:02

|

662人浏览过

|

来源于php中文网

原创

Flask应用中定时刷新CSV数据的高效策略

本文旨在探讨在Flask应用中实现CSV文件定时刷新数据的策略。针对Web服务器不应执行耗时阻塞任务的原则,核心思想是将数据抓取和CSV更新逻辑从Flask主应用中解耦,通过独立的后台进程或任务调度工具(如Cron、APScheduler、Celery)来定时执行。文章将详细介绍各种实现方案及其优缺点,并提供关键的并发访问和数据一致性处理建议,确保Web应用能稳定、高效地读取最新数据。

理解核心问题:Web服务器与后台任务的分离

在web开发中,尤其是使用flask这样的微服务框架时,一个基本原则是web服务器应专注于处理http请求并快速响应,而不应执行耗时或阻塞性的后台任务,如数据抓取(scraping)或文件i/o操作。将这类任务直接嵌入到flask应用的主线程中,会导致请求响应延迟,甚至阻塞其他用户的请求。因此,对于“每10分钟自动刷新csv文件”的需求,最佳实践是将数据更新逻辑与flask应用本身解耦,让其在独立的进程中运行。flask应用只需负责读取已更新的csv文件。

解决方案一:利用操作系统级任务调度(Cron Job)

对于部署在Linux/Unix环境下的应用,Cron Job是最简单直接的定时任务解决方案。它允许用户在操作系统层面配置定时执行脚本或命令。

工作原理:

  1. 编写一个独立的Python脚本,该脚本负责执行数据抓取、处理并更新CSV文件的逻辑。
  2. 使用crontab命令配置,让该脚本每10分钟执行一次。

示例(update_csv.py):

# update_csv.py
import pandas as pd
import datetime
import os

def scrape_and_update_csv():
    # 模拟数据抓取和处理
    print(f"[{datetime.datetime.now()}] 开始抓取数据并更新CSV...")
    data = {
        'game': ['Game A', 'Game B', 'Game C'],
        'stake': [1.5, 2.0, 1.8],
        'timestamp': [datetime.datetime.now()] * 3
    }
    df = pd.DataFrame(data)

    # 定义CSV文件路径
    # 注意:这里的路径应是绝对路径,以便cron正确找到
    csv_file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data.csv')

    # 将数据保存到CSV
    df.to_csv(csv_file_path, index=False)
    print(f"[{datetime.datetime.now()}] CSV文件已更新:{csv_file_path}")

if __name__ == "__main__":
    scrape_and_update_csv()

配置Cron Job:

  1. 打开终端,输入 crontab -e。

  2. 在打开的文件末尾添加一行(确保Python环境和脚本路径正确):

    */10 * * * * /usr/bin/python3 /path/to/your/update_csv.py >> /path/to/your/cron.log 2>&1
    • */10 * * * * 表示每10分钟执行一次。
    • /usr/bin/python3 是Python解释器的路径。
    • /path/to/your/update_csv.py 是你编写的Python脚本的绝对路径。
    • >> /path/to/your/cron.log 2>&1 将脚本的输出重定向到日志文件,便于调试。

优点: 简单、可靠,系统资源占用低。 缺点: 平台依赖(主要用于类Unix系统),任务管理不够灵活(例如,难以从Python代码中动态调度或取消任务)。

解决方案二:使用Python任务调度库(APScheduler)

APScheduler(Advanced Python Scheduler)是一个轻量级的Python库,允许你在Python应用内部(或独立脚本中)安排任务。它支持多种调度器类型,如BlockingScheduler(用于独立脚本)和BackgroundScheduler(用于在应用内部以非阻塞方式运行)。

工作原理:

  1. 创建一个独立的Python脚本,使用BlockingScheduler来定时执行CSV更新函数。
  2. 在Flask应用中,只需正常读取该CSV文件。

示例(scheduler_app.py):

# scheduler_app.py
from apscheduler.schedulers.blocking import BlockingScheduler
import pandas as pd
import datetime
import os
import logging

# 配置日志,方便调试
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

def scrape_and_update_csv():
    logging.info("开始抓取数据并更新CSV...")
    try:
        # 模拟数据抓取和处理
        data = {
            'game': [f'Game {i}' for i in range(1, 4)],
            'stake': [1.5 + i * 0.1 for i in range(3)],
            'timestamp': [datetime.datetime.now()] * 3
        }
        df = pd.DataFrame(data)

        # 定义CSV文件路径
        # 同样建议使用绝对路径
        csv_file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data.csv')

        # 将数据保存到CSV
        df.to_csv(csv_file_path, index=False)
        logging.info(f"CSV文件已更新:{csv_file_path}")
    except Exception as e:
        logging.error(f"更新CSV文件失败: {e}")

if __name__ == '__main__':
    scheduler = BlockingScheduler()
    # 每10分钟执行一次 scrape_and_update_csv 函数
    scheduler.add_job(scrape_and_update_csv, 'interval', minutes=10)

    logging.info("APScheduler已启动,等待任务执行...")
    try:
        scheduler.start()
    except (KeyboardInterrupt, SystemExit):
        logging.info("APScheduler已停止。")

运行方式: 将scheduler_app.py作为一个独立的Python脚本运行:python3 scheduler_app.py。 Flask应用和这个调度器脚本将作为两个独立的进程运行。

优点: 跨平台,纯Python实现,任务管理更灵活。 缺点: 仍需独立进程运行,不适合分布式任务。

解决方案三:使用任务队列(Celery)

对于更复杂、需要分布式处理、或者任务执行时间可能较长的场景,Celery是一个强大的选择。它是一个异步任务队列/基于分布式消息传递的作业队列,可以处理大量操作。

工作原理:

  1. Broker(消息代理): Celery使用消息代理来协调任务。常见的有Redis或RabbitMQ。
  2. Worker(工作者): Celery Worker是独立的进程,它们监听Broker,接收任务并执行。
  3. Client(客户端): Flask应用作为客户端,将任务发送到Broker。
  4. Scheduler(调度器,如Celery Beat): Celery Beat可以作为独立的进程运行,根据预设的调度计划将任务发送到Broker。

示例概述:

企奶奶
企奶奶

一款专注于企业信息查询的智能大模型,企奶奶查企业,像聊天一样简单。

下载
  1. 安装: pip install celery redis (如果使用Redis作为Broker)。

  2. 创建Celery应用(celery_app.py):

    # celery_app.py
    from celery import Celery
    import pandas as pd
    import datetime
    import os
    import logging
    
    logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
    
    celery_app = Celery(
        'csv_updater',
        broker='redis://localhost:6379/0', # 替换为你的Redis地址
        backend='redis://localhost:6379/0'
    )
    
    @celery_app.task
    def scrape_and_update_csv_task():
        logging.info("Celery任务:开始抓取数据并更新CSV...")
        try:
            data = {
                'game': [f'Game {i}' for i in range(1, 4)],
                'stake': [1.5 + i * 0.1 for i in range(3)],
                'timestamp': [datetime.datetime.now()] * 3
            }
            df = pd.DataFrame(data)
            csv_file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data.csv')
            df.to_csv(csv_file_path, index=False)
            logging.info(f"Celery任务:CSV文件已更新:{csv_file_path}")
        except Exception as e:
            logging.error(f"Celery任务:更新CSV文件失败: {e}")
  3. 启动Celery Worker: 在终端中运行:celery -A celery_app worker --loglevel=info

  4. 使用Celery Beat进行定时调度: 创建celeryconfig.py文件:

    # celeryconfig.py
    from datetime import timedelta
    
    CELERY_BEAT_SCHEDULE = {
        'update-csv-every-10-minutes': {
            'task': 'celery_app.scrape_and_update_csv_task',
            'schedule': timedelta(minutes=10),
            'args': (),
        },
    }
    CELERY_TIMEZONE = 'Asia/Shanghai' # 根据需要设置时区

    启动Celery Beat:celery -A celery_app beat -s celerybeat-schedule --loglevel=info

优点: 强大、可扩展、支持分布式、任务重试、结果存储等高级功能,适用于生产环境复杂任务。 缺点: 配置相对复杂,引入了额外的组件(Broker、Worker、Beat)。

数据一致性与文件锁定注意事项

当一个后台进程定时更新CSV文件,而Flask应用同时尝试读取该文件时,可能会出现数据不一致或文件锁定问题。

  1. 原子性写入: 避免直接覆盖正在读取的文件。最佳实践是:

    • 将新数据写入一个临时文件(例如data.csv.tmp)。
    • 当写入完成后,原子性地将临时文件重命名为目标文件(data.csv)。大多数操作系统对文件重命名操作是原子的。
    # 修改 scrape_and_update_csv 函数
    def scrape_and_update_csv():
        # ... 数据抓取逻辑 ...
        csv_file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data.csv')
        temp_file_path = csv_file_path + '.tmp'
    
        df.to_csv(temp_file_path, index=False) # 写入临时文件
        os.replace(temp_file_path, csv_file_path) # 原子性替换
        logging.info(f"CSV文件已更新:{csv_file_path}")
  2. 数据库替代方案: 如果数据量较大或对并发访问有更高要求,将数据存储在数据库(如SQLite,因为Flask应用已配置SQLAlchemy)而不是CSV文件是更健壮的选择。

    • 优点: 数据库本身就提供了事务和并发控制机制,避免了文件锁定问题。
    • 实现: 后台任务将数据抓取后写入数据库,Flask应用则通过SQLAlchemy从数据库中查询数据。这会使数据访问更加高效和可靠。

Flask应用中的数据读取

无论采用哪种后台更新策略,Flask应用在处理用户请求时,只需从固定的CSV文件路径读取数据即可。

# from .views import views (假设在views.py中)
from flask import Blueprint, render_template
import pandas as pd
import os

views = Blueprint('views', __name__)

@views.route('/')
def home():
    csv_file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data.csv')

    # 确保文件存在,并处理可能的文件不存在或读取错误
    if os.path.exists(csv_file_path):
        try:
            df = pd.read_csv(csv_file_path)
            # 假设你的CSV有 'game' 和 'stake' 列
            games_data = df.to_dict(orient='records')
            return render_template("home.html", games=games_data)
        except Exception as e:
            print(f"读取CSV文件失败: {e}")
            return render_template("home.html", games=[], error="无法加载数据")
    else:
        return render_template("home.html", games=[], error="数据文件不存在,请稍后再试")

请注意,os.path.dirname(os.path.abspath(__file__)) 仅在当前文件直接运行时有效。在Flask应用中,你需要确保data.csv的路径是相对于你的项目根目录或Flask应用实例可访问的路径。

总结

在Flask等Web应用中实现定时数据刷新,核心原则是将耗时操作从Web服务器的请求-响应循环中分离出来。本文介绍了三种主流策略:

  1. Cron Job: 适用于简单的、部署在Linux环境下的定时任务,配置直接,开销小。
  2. APScheduler: 提供Python原生的任务调度能力,跨平台,适合作为独立脚本运行。
  3. Celery: 针对复杂的、分布式、高并发任务的强大解决方案,功能丰富但配置相对复杂。

无论选择哪种方案,都应注意数据一致性和文件访问的原子性。对于更严谨的数据管理,将数据存储在数据库中是比CSV文件更推荐的方案,因为它提供了更完善的并发控制和数据完整性保障。通过合理选择和实施这些策略,可以确保Flask应用能够稳定、高效地提供最新数据,同时保持其响应性。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
rabbitmq和kafka有什么区别
rabbitmq和kafka有什么区别

rabbitmq和kafka的区别:1、语言与平台;2、消息传递模型;3、可靠性;4、性能与吞吐量;5、集群与负载均衡;6、消费模型;7、用途与场景;8、社区与生态系统;9、监控与管理;10、其他特性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

202

2024.02.23

Python Flask框架
Python Flask框架

本专题专注于 Python 轻量级 Web 框架 Flask 的学习与实战,内容涵盖路由与视图、模板渲染、表单处理、数据库集成、用户认证以及RESTful API 开发。通过博客系统、任务管理工具与微服务接口等项目实战,帮助学员掌握 Flask 在快速构建小型到中型 Web 应用中的核心技能。

86

2025.08.25

Python Flask Web框架与API开发
Python Flask Web框架与API开发

本专题系统介绍 Python Flask Web框架的基础与进阶应用,包括Flask路由、请求与响应、模板渲染、表单处理、安全性加固、数据库集成(SQLAlchemy)、以及使用Flask构建 RESTful API 服务。通过多个实战项目,帮助学习者掌握使用 Flask 开发高效、可扩展的 Web 应用与 API。

72

2025.12.15

什么是分布式
什么是分布式

分布式是一种计算和数据处理的方式,将计算任务或数据分散到多个计算机或节点中进行处理。本专题为大家提供分布式相关的文章、下载、课程内容,供大家免费下载体验。

328

2023.08.11

分布式和微服务的区别
分布式和微服务的区别

分布式和微服务的区别在定义和概念、设计思想、粒度和复杂性、服务边界和自治性、技术栈和部署方式等。本专题为大家提供分布式和微服务相关的文章、下载、课程内容,供大家免费下载体验。

235

2023.10.07

pip安装使用方法
pip安装使用方法

安装步骤:1、确保Python已经正确安装在您的计算机上;2、下载“get-pip.py”脚本;3、按下Win + R键,然后输入cmd并按下Enter键来打开命令行窗口;4、在命令行窗口中,使用cd命令切换到“get-pip.py”所在的目录;5、执行安装命令;6、验证安装结果即可。大家可以访问本专题下的文章,了解pip安装使用方法的更多内容。

339

2023.10.09

更新pip版本
更新pip版本

更新pip版本方法有使用pip自身更新、使用操作系统自带的包管理工具、使用python包管理工具、手动安装最新版本。想了解更多相关的内容,请阅读专题下面的文章。

412

2024.12.20

pip设置清华源
pip设置清华源

设置方法:1、打开终端或命令提示符窗口;2、运行“touch ~/.pip/pip.conf”命令创建一个名为pip的配置文件;3、打开pip.conf文件,然后添加“[global];index-url = https://pypi.tuna.tsinghua.edu.cn/simple”内容,这将把pip的镜像源设置为清华大学的镜像源;4、保存并关闭文件即可。

761

2024.12.23

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

10

2026.01.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7.9万人学习

Git 教程
Git 教程

共21课时 | 3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号