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

PyInstaller打包exe异常:重复创建SQLite表陷入死循环

PyInstaller打包多进程程序后重复创建数据库的解决方法

问题描述

Python代码在PyCharm中直接运行完全正常,但用PyInstaller打包为.exe文件后,启动时会反复创建数据库文件,并且报错“products表已存在”,程序陷入重复执行初始化逻辑的状态。

原代码

if __name__ == '__main__':
    now = datetime.now()
    time_now = now.strftime("%H %M")
    file_name = r'data/result1 ' + (str(date.today())) + ' ' + time_now + '.db'
    ittr = 0
    conn = sqlite3.connect(file_name)
    cursor = conn.cursor()
    cursor.execute("""CREATE TABLE "products" (
                "категория" TEXT NOT NULL,
                "производитель" TEXT NOT NULL,
                "название"  TEXT NOT NULL,
                "цена"  TEXT NOT NULL,
                "продажи"   INTEGER NOT NULL,
                "наличие"   TEXT NOT NULL,
                "рейтинг"   TEXT NOT NULL,
                "отзывы"    TEXT NOT NULL,
                "айди"  TEXT NOT NULL
            );
                           """)
    conn.commit()
    with multiprocessing.Pool(1) as p:
        for i in range(190):
            start_id = 1 + 10000 * ittr
            end_id = 10000 + 10000 * ittr
            ittr = ittr + 1
            p.apply_async(main, args=(start_id,end_id, ), callback=data_processing)
        p.close()
        p.join()

问题原因

Windows系统下,multiprocessing启动子进程时会重新加载主脚本文件。PyInstaller打包后的程序,子进程启动时会再次触发if __name__ == '__main__':代码块,导致数据库初始化逻辑被重复执行,进而反复创建数据库和尝试创建已存在的表。

解决方案

修改步骤:

  1. 添加multiprocessing.freeze_support():这是PyInstaller打包Windows多进程程序的必要操作,用于处理子进程启动的特殊逻辑,避免主代码重复执行。
  2. 封装数据库初始化逻辑:将创建数据库和表的代码放到单独函数中,确保仅主进程执行一次。
  3. 给CREATE TABLE加IF NOT EXISTS:作为兜底措施,即使意外重复执行也不会抛出表已存在的错误。

修改后的代码

import sqlite3
import datetime
from datetime import date
import multiprocessing

def init_database():
    now = datetime.datetime.now()
    time_now = now.strftime("%H %M")
    file_name = r'data/result1 ' + (str(date.today())) + ' ' + time_now + '.db'
    conn = sqlite3.connect(file_name)
    cursor = conn.cursor()
    # 添加IF NOT EXISTS,避免表已存在时报错
    cursor.execute("""CREATE TABLE IF NOT EXISTS "products" (
                "категория" TEXT NOT NULL,
                "производитель" TEXT NOT NULL,
                "название"  TEXT NOT NULL,
                "цена"  TEXT NOT NULL,
                "продажи"   INTEGER NOT NULL,
                "наличие"   TEXT NOT NULL,
                "рейтинг"   TEXT NOT NULL,
                "отзывы"    TEXT NOT NULL,
                "айди"  TEXT NOT NULL
            );
                           """)
    conn.commit()
    conn.close()
    return file_name

def main(start_id, end_id):
    # 此处保留原main函数的业务逻辑
    pass

def data_processing(result):
    # 此处保留原回调函数的逻辑
    pass

if __name__ == '__main__':
    # 必须添加,处理Windows多进程打包问题
    multiprocessing.freeze_support()
    
    # 仅主进程执行数据库初始化
    db_file = init_database()
    
    ittr = 0
    with multiprocessing.Pool(1) as p:
        for i in range(190):
            start_id = 1 + 10000 * ittr
            end_id = 10000 + 10000 * ittr
            ittr += 1
            p.apply_async(main, args=(start_id, end_id, ), callback=data_processing)
        p.close()
        p.join()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 21:15:05