Python + PostgreSQL 批量图片分发脚本:分类、去重、断点续拷贝

现有涉及图片保存的系统中,图片通常存储在服务器文件系统,路径写在数据库里。

例如:

  • 表 A 存图片路径 i.location
  • 表 B 存业务区县 q.qx
  • 业务需求:按区县把图片重新整理分目录

本文分享一个生产级 Python 脚本,可处理上万文件,支持断点续拷贝、去重、错误耐受。


环境准备

bash 复制代码
yum install postgresql-devel gcc python3-devel -y
pip3 install psycopg2-binary

脚本完整代码(含注释解读)

python 复制代码
import os 
import psycopg2
import shutil
import sys

# PostgreSQL数据库配置
db_config = {
    'host': '123.',
    'user': '',
    'password': '*?.',
    'database': '',
    'port': 5432
}

# 图片导出根目录
EXPORT_DIR = '/project/WYApp/photo_export'

def main():
    # 用于记录已处理过的 path(用于扩展断点续传)
    processed_paths = set()
    
    try:
        # 1. 建立数据库连接
        connection = psycopg2.connect(**db_config)
        cursor = connection.cursor()
        
        # 2. SQL:使用 JOIN + DISTINCT 避免重复
        query = """
        SELECT DISTINCT i.location, q.qx
        FROM wyfwimg i 
        INNER JOIN sde.jwbld_wy q ON i.fwid = q.uuid 
        WHERE q.qx IS NOT NULL AND i.location IS NOT NULL AND q.qx = '密云区'
        ORDER BY q.qx, i.location
        """
        
        cursor.execute(query)
        results = cursor.fetchall()
        print(f"去重后找到 {len(results)} 条图片记录")

        # 用于统计
        success_count = fail_count = skip_count = 0
        
        # 3. 遍历每条记录
        for location, qx in results:
            try:
                # ------区县字段清洗:过滤非法字符,避免目录报错
                safe_qx = "".join(c for c in str(qx) if c.isalnum() or c in (' ', '-', '_')).rstrip()
                
                # ------获取文件名
                filename = os.path.basename(location)
                
                # ------源文件路径
                source_file = location
                
                # 4. 源文件是否存在?(防止数据库脏数据)
                if not os.path.exists(source_file):
                    fail_count += 1
                    print(f"✗ 源文件不存在: {source_file}")
                    continue
                
                # ------目标目录 = 导出根目录 + 区县目录
                target_dir = os.path.join(EXPORT_DIR, safe_qx)
                os.makedirs(target_dir, exist_ok=True)
                
                target_file = os.path.join(target_dir, filename)
                
                # 5. 断点续拷贝:如果文件已存在则跳过
                if os.path.exists(target_file):
                    skip_count += 1
                    print(f"⏭️ 已存在: {safe_qx}/{filename}")
                    continue
                
                # 6. 复制文件(保留元信息:时间、权限等)
                shutil.copy2(source_file, target_file)
                success_count += 1
                print(f"✅ 成功: {safe_qx}/{filename}")
                    
            except Exception as e:
                fail_count += 1
                print(f"❌ 处理失败: {location}, 错误: {e}")
        
        print("\n===== 导出完成 =====")
        print(f"✅ 成功复制: {success_count}")
        print(f"⏭️ 跳过已有: {skip_count}")
        print(f"❌ 失败: {fail_count}")
        
    except Exception as e:
        print(f"🚨 数据库连接失败: {e}")
        sys.exit(1)
    finally:
        # ------确保资源释放
        if 'connection' in locals():
            cursor.close()
            connection.close()

if __name__ == "__main__":
    main()

代码关键功能说明 ✅

Python 功能 描述
psycopg2.connect() 连接 PostgreSQL 数据库
SQL DISTINCT + JOIN 避免重复图片路径
字符串过滤 .isalnum() 目录命名安全处理
os.path.exists() 判断文件存在(防脏数据)
os.makedirs(..., exist_ok=True) 自动创建分类目录
shutil.copy2() 完整复制文件,保留时间属性
断点续拷贝逻辑 文件存在自动跳过,支持长任务恢复
异常捕获 单张失败不影响整体执行
最终统计输出 一目了然执行效果

推荐运行方式(生产)

后台运行并保存日志:

bash 复制代码
nohup python3 export_photos.py > export.log 2>&1 &
tail -f export.log

压缩导出目录:

bash 复制代码
tar -czvf photo_export.tar.gz photo_export > /tmp/tar.txt 2>&1 &
tail -f /tmp/tar.txt

或者快速打包

bash 复制代码
tar -cf shijingshan_photos.tar photo_export/

下载文件:

bash 复制代码
scp user@ip:/project/WYApp/photo_export.tar.gz ./

相关推荐
唐老板2 分钟前
uuidv7 来了:为什么别再拿 uuidv4 当主键了
数据库
锋行天下7 小时前
langgraph 后端发自定义数据,前端接收方法概括
人工智能·python
benchmark_cc9 小时前
用 QuantDash 读取单只股票五档盘口:抽样、缺失值检查与复现记录
python·数据分析·pandas·量化交易·股票数据·quantdash
曲径海盗9 小时前
【Python 学习第 55 天】列表基础
python·学习笔记·编程入门
专注仿真9 小时前
知识问答模型用到的算法集详解及代码实例
python·算法·代码·大模型训练·控制算法
jyOverQ10 小时前
我写了一个 CSDN Markdown 图片助手:告别本地图片逐张上传
python·工具·csdn
lzx_00211 小时前
Linux 进程(三) 从进程状态到僵尸进程、孤儿进程
linux·服务器
SelectDB13 小时前
让变更流出 Doris:Apache Doris 5.0 基于增量计算的 CDC 技术解析
数据库
刘马想放假13 小时前
CANviz 使用指南|Linux 安装、DBC 解码、实时曲线与 J1939 实战
linux·python·websocket
这个DBA有点耶13 小时前
MCP隔离层+行级语义审计+输出校验:AI访问数据库的安全边界拆解
数据库·人工智能·ai编程