Python实现将MySQL中所有表的数据都导出为CSV文件并压缩

2025-03-27 02:50

本文主要是介绍Python实现将MySQL中所有表的数据都导出为CSV文件并压缩,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《Python实现将MySQL中所有表的数据都导出为CSV文件并压缩》这篇文章主要为大家详细介绍了如何使用Python将MySQL数据库中所有表的数据都导出为CSV文件到一个目录,并压缩为zip文件到...

pythonmysql数据库中所有表的数据都导出为CSV文件到一个目录,并压缩为zip文件到另一个目录下,然后解压缩这个目录中的所有zip文件到第三个目录下。不使用Pandas库,需要考虑SQL结果集是大数据量分批数据导出的情况,通过多线程和异步操作来提高程序性能,程序需要异常处理和输出,输出出错时的错误信息,每次每个查询导出数据的运行状态和表数据行数以及运行时间戳,导出时间,输出每个文件记录数量的日志。

脚本已在考虑大数据量、异常处理和性能优化的基础上进行了全面设计,能够处理大多数常见场景。根据具体需求可进一步调整批量大小(BATch_size)和线程数(max_workers)以获得最佳性能。

import os
import csv
import zipfile
import logging
import mysql.connector
from datetime import datetime
import time
import concurrent.futures
import glob

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('data_export.log'),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger(__name__)

def export_table_to_csv(table_name, csv_path, db_config, batch_size=1000):
    """导出单个表的数据到CSV文件,分批处理"""
    conn = None
    cursor = None
    total_rows = 0
    try:
        conn = mysql.connector.connect(**db_config)
        cursor = conn.cursor()

        # 获取数据并写入CSV
        with open(csv_path, 'w', newline='', encoding='utf-8') as csvfile:
            writer = csv.writer(csvfile)
            
            # 执行查询并获取列名
            cursor.execute(f"SELECT * FROM `{table_name}`")
            columns = [col[0] for col in cursor.description]
            writer.writerow(columns)
            
            # 分批获取数据
            while True:
                rows = cursor.fetchmany(batch_size)
                if not rows:
                    break
                writer.writerows(rows)
                total_rows += len(rows)
                logger.debug(f"{table_name} 已导出 {total_rows} 行")

        logger.info(f"{table_name} CSV导出完成,总行数:{total_rows}")
        return total_rows

    except Exception as e:
        logger.error(f"导出表 {table_name} 失败: {str(e)}", exc_info=True)
        raise
    finally:
        if cursor:
            cursor.close()
        if conn and conn.is_connected():
            conn.close()

def compress_to_zip(source_path, zip_path):
    """压缩文件为ZIP格式"""
    try:
     China编程   with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
            zipf.write(source_path, arcname=os.path.basename(source_path))
        logger.info(f"成功压缩 {source_path} 到 {zip_path}")
    except Exception as e:
        logger.error(f"压缩 {source_path} 失败: {str(e)}", exc_info=True)
        raise

def process_table(table_name, db_config, csv_dir, zip_dir):
    """处理单个表的导出和压缩"""
    start_time = time.time()
    logger.info(f"开始处理表: {table_name}")
    status = "成功"
    rows_exported = 0

    try:
        # 定义文件路径
        csv_filename = f"{table_name}.csv"
        zip_filename = f"{table_name}.zip"
        csv_path = os.path.join(csv_dir, csv_filename)
        zip_path = os.path.join(zip_dir, zip_filename)

        # 导出CSV
        rows_exported = export_table_to_csv(table_name, csv_path, db_config)
        
        # 压缩文件
        compress_to_zip(csv_path, zip_path)

    except Exception as e:
        status = f"失败: {str(e)}"
        # 清理可能存在的中间文件
        for path in [csv_path, zip_path]:
            if path and os.path.exists(path):
                try:
                    os.remove(path)
                    logger.warning(f"已清理文件: {path}")
                except Exception as clean_error:
                    logger.error(f"清理文件失败: {clean_error}")

    finally:
        duration = time.time() - start_time
        log_message = (
            f"表处理完成 - 表名: {table_name}, "
            f"状态: {status}, "
            f"导出行数: {rows_exported}, "
            f"耗时: {duration:.2f}秒"
        )
        logger.info(log_message)

def unzip_files(zip_dir, unzip_dir):
    """解压指定目录中的所有ZIP文件"""
    zip_files = glob.glob(os.path.join(zip_dir, '*.zip'))
    if not zip_files:
        logger.warning("未找到ZIP文件,跳过解压")
        return

    with concurrent.futures.ThreadPoolExecutor() as executor:
        futures = []
        for zip_path in zip_files:
            futures.append(executor.submit(
                lambda: extract_zip(zip_path, unzip_dir)
            ))
        for future in concurrent.futures.as_completed(futures):
            try:
                future.result()
            except Exception as e:
                logger.error(f"解压过程中发生错误: {str(e)}")

def extract_zip(zip_path, unzip_dir):
    """解压单个ZIP文件"""
    try:
        start_time = time.time()
        with zipfile.ZipFile(zip_path, 'r') as zip_ref:
            zip_ref.extractall(unzip_dir)
        duration = time.time() - start_time
        logger.info(f"解压完成: {zip_path} => {unzip_dir} (耗时: {duration:.2f}秒)")
    except Exception as e:
        logger.error(f"解压 {zip_path} 失败: {str(e)}", exc_info=True)
        raise

def main():
    # 配置参数
    db_config = {
        'host': 'localhost',
        'user': 'your_username',
        'password': 'your_password',
        'database': 'your_database'
    }
    
    # 目录配置
    base_dir = os.path.dirname(os.path.abspath(__file__))
    csv_dir = os.path.join(base_dir, 'csv_exports')
    zip_dir = os.path.join(base_dir, 'zip_archives')
    unzip_dir = os.path.join(base_dir, 'unzipped_files')

    # 创建目录
    for dir_path in [csv_dir, zip_dir, unzip_dir]:
        os.makedirs(dir_path, exist_ok=True)
        logger.info(f"目录已准备: {dir_path}")

    # 获取所有表名
    try:
        conn = mysql.connector.connect(**db_config)
        cursor = conn.cursorjs()
        cursor.execute("SHOW TABLES")
        tables = [table[0] for table in cursor.fetchall()]
        logger.info(f"发现 {len(tables)} 个需要处理的表")
    except Exception as e:
        logger.error(f"获取数据库表失败: {str(e)}", exc_info=True)
        return
    finally:
        if 'cursor' in locals():
            cursor.close()
        if 'conn' in locals() and conn.is_connected():
            conn.close()

    # 处理所有表(多线程导出和压缩)
    with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
        futures = []
        for table in tables:
            futures.append(executor.submit(
                process_table,
                table,
                db_config,
               China编程 csv_dir,
                zip_dir
            ))

        # 处理任务结果
        for future in concurrent.futures.as_completed(futures):
            try:
                future.result()
            except Exception as e:
                logger.error(f"表处理异常: {str(e)}")

    # 解压所有ZIP文件(多线程解压)
    logger.info("开始解压所有ZIP文件")
    unzip_files(zip_dir, unzip_dir)
    logger.info("全部处理流程完成")

if __name__ == "__main__":
    main()

关键特性说明:

1.分批处理大数据:

  • 使用fetchmany(batch_size)分批获取数据(默认每批1000行)
  • 流式处理减少内存占用

2.多线程处理:

  • 使用ThreadPoolExecutor并行处理不同表的导出和压缩
  • 独立的数据库连接池(每个线程有自己的连接)
  • 并行解压处理

3.异常处理:

  • 全面的try-http://www.chinasem.cnexcept块覆盖所有关键操作
  • 自动清理失败时产生的中间文件
  • 详细的错误日志记录(包含堆栈跟踪)

4.日志记录:

  • 同时输出到文件和终端
  • 记录时间戳、操作类型、状态、耗时等关键信息
  • 包含每个表的处理结果统计

5.文件管理:

  • 自动创建所需目录
  • 使用ZIP_DEFLATED进行高效压缩
  • 安全的文件路径处理

6.性能优化:

  • 使用服务器端游标避免内存过载
  • 可配置的批量大小和线程数
  • 异步I/O操作

使用说明:

安装依赖:

pip install mysql-connector-python

修改配置:

更新db_config中的数据库连接信息

根据需要调整目录路径(csv_dir, zip_dir, unzip_dir)

运行脚本:

python script.py

查看日志:

实时终端输出

详细日志文件data_export.log

扩展建议:

通过命令行参数接受数据库配置和目录路径

添加邮件通知功能(处理完成或失败时通知)

实现断点续传功能

添加文件校验(MD5校验和)

支持配置文件(YAML/jsON格式)

添加进度条显示

到此这篇关于PnlHKgwAzbHython实现将MySQL中所有表的数据都导出为CSV文件并压缩的文章就介绍到这了,更多相关Python MySQL数据导出为CSV内容请搜索编程China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持China编程(www.chinasem.cn)!

这篇关于Python实现将MySQL中所有表的数据都导出为CSV文件并压缩的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1153956

相关文章

python+opencv处理颜色之将目标颜色转换实例代码

《python+opencv处理颜色之将目标颜色转换实例代码》OpenCV是一个的跨平台计算机视觉库,可以运行在Linux、Windows和MacOS操作系统上,:本文主要介绍python+ope... 目录下面是代码+ 效果 + 解释转HSV: 关于颜色总是要转HSV的掩膜再标注总结 目标:将红色的部分滤

Python 中的异步与同步深度解析(实践记录)

《Python中的异步与同步深度解析(实践记录)》在Python编程世界里,异步和同步的概念是理解程序执行流程和性能优化的关键,这篇文章将带你深入了解它们的差异,以及阻塞和非阻塞的特性,同时通过实际... 目录python中的异步与同步:深度解析与实践异步与同步的定义异步同步阻塞与非阻塞的概念阻塞非阻塞同步

Python Dash框架在数据可视化仪表板中的应用与实践记录

《PythonDash框架在数据可视化仪表板中的应用与实践记录》Python的PlotlyDash库提供了一种简便且强大的方式来构建和展示互动式数据仪表板,本篇文章将深入探讨如何使用Dash设计一... 目录python Dash框架在数据可视化仪表板中的应用与实践1. 什么是Plotly Dash?1.1

使用Java实现通用树形结构构建工具类

《使用Java实现通用树形结构构建工具类》这篇文章主要为大家详细介绍了如何使用Java实现通用树形结构构建工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录完整代码一、设计思想与核心功能二、核心实现原理1. 数据结构准备阶段2. 循环依赖检测算法3. 树形结构构建4. 搜索子

浅谈mysql的sql_mode可能会限制你的查询

《浅谈mysql的sql_mode可能会限制你的查询》本文主要介绍了浅谈mysql的sql_mode可能会限制你的查询,这个问题主要说明的是,我们写的sql查询语句违背了聚合函数groupby的规则... 目录场景:问题描述原因分析:解决方案:第一种:修改后,只有当前生效,若是mysql服务重启,就会失效;

MySQL多列IN查询的实现

《MySQL多列IN查询的实现》多列IN查询是一种强大的筛选工具,它允许通过多字段组合快速过滤数据,本文主要介绍了MySQL多列IN查询的实现,具有一定的参考价值,感兴趣的可以了解一下... 目录一、基础语法:多列 IN 的两种写法1. 直接值列表2. 子查询二、对比传统 OR 的写法三、性能分析与优化1.

在C#中调用Python代码的两种实现方式

《在C#中调用Python代码的两种实现方式》:本文主要介绍在C#中调用Python代码的两种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#调用python代码的方式1. 使用 Python.NET2. 使用外部进程调用 Python 脚本总结C#调

Python下载Pandas包的步骤

《Python下载Pandas包的步骤》:本文主要介绍Python下载Pandas包的步骤,在python中安装pandas库,我采取的方法是用PIP的方法在Python目标位置进行安装,本文给大... 目录安装步骤1、首先找到我们安装python的目录2、使用命令行到Python安装目录下3、我们回到Py

MySQL新增字段后Java实体未更新的潜在问题与解决方案

《MySQL新增字段后Java实体未更新的潜在问题与解决方案》在Java+MySQL的开发中,我们通常使用ORM框架来映射数据库表与Java对象,但有时候,数据库表结构变更(如新增字段)后,开发人员可... 目录引言1. 问题背景:数据库与 Java 实体不同步1.1 常见场景1.2 示例代码2. 不同操作

Python GUI框架中的PyQt详解

《PythonGUI框架中的PyQt详解》PyQt是Python语言中最强大且广泛应用的GUI框架之一,基于Qt库的Python绑定实现,本文将深入解析PyQt的核心模块,并通过代码示例展示其应用场... 目录一、PyQt核心模块概览二、核心模块详解与示例1. QtCore - 核心基础模块2. QtWid