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

cx_Freeze打包exe偶发sqlite3.OperationalError:无法打开数据库文件

解决cx_Freeze打包exe后sqlite3数据库偶尔无法打开的问题

核心问题分析

打包后exe运行时的当前工作目录不一定是exe所在目录,导致getcwd()获取的路径不可靠;同时打包时若将game.db纳入资源文件,可能被放到只读的临时解压目录,无法写入;权限不足或数据库锁定也会引发偶发错误。


具体解决方案

1. 修复数据库路径获取逻辑

替换依赖getcwd()的路径获取方式,改为获取exe的实际所在目录(打包前后均适用),并确保目录创建逻辑更健壮:

import sys
import os
import sqlite3

# 获取当前程序的根目录(开发/打包模式通用)
if getattr(sys, 'frozen', False):
    # 打包为exe后的运行模式
    root_dir = os.path.dirname(sys.executable)
else:
    # 开发时直接运行py文件的模式
    root_dir = os.path.dirname(os.path.abspath(__file__))

# 定义数据库目录和文件路径
db_dir = os.path.join(root_dir, "Database")
db_path = os.path.join(db_dir, "game.db")

# 先确保数据库目录存在
if not os.path.exists(db_dir):
    try:
        os.makedirs(db_dir)
    except OSError as e:
        raise RuntimeError(f"创建数据库目录失败: {str(e)}")

# 连接数据库,添加超时参数避免锁定
try:
    connection = sqlite3.connect(db_path, timeout=10)
    connection.execute("PRAGMA foreign_keys = 1;")
    cursor = connection.cursor()
except sqlite3.OperationalError as e:
    raise RuntimeError(f"打开数据库失败: {str(e)}")

# 保持原有表初始化逻辑
def run(sql):
    cursor.execute(sql)
    connection.commit()
    return [i for i in cursor]

run("CREATE TABLE IF NOT EXISTS accounts (playerName TEXT PRIMARY KEY, playerPassword TEXT);")
run("CREATE TABLE IF NOT EXISTS scores (playerName REFERENCES accounts(playerName), difficulty TEXT, score INTEGER);")

2. 调整setup.py打包配置

移除include_files中的game.db,避免打包只读的数据库文件,让程序在运行时自动创建可写的数据库:

import cx_Freeze
import pkgutil
from os.path import join as path_join

def get_all_packages():
    return [i.name for i in list(pkgutil.iter_modules()) if i.ispkg]

executables = [cx_Freeze.Executable('main.py', base="Win32GUI",
               target_name="Push-Ups Game", icon=path_join("Images", "Push-Ups Game Logo.ico"))]

packages = ["collections", "encodings", "importlib", "pygame", "cv2", "mediapipe",
            "math", "sqlite3", "random", "numpy", "time", "os", "re", "ctypes",
            "matplotlib", "logging", "urllib", "packaging", "PIL", "pyparsing",
            "html", "cycler", "dateutil", "kiwisolver", "json", "xml", "http", "attr", "sys"]

cx_Freeze.setup(
    name="Game",
    options={"build_exe": 
             {"includes": packages,
              "excludes": [i for i in get_all_packages() if i not in packages],
              "include_files": ["Music/", "Images/"]}},  # 移除game.db
    executables=executables
)

3. 解决权限与锁定问题

  • 不要将exe放在系统保护目录(如C:\Program Files),建议放到用户目录(如Documents、桌面)或自定义非系统目录,避免写入权限不足。
  • 添加timeout=10参数让sqlite3连接等待10秒再报错,减少多线程/进程场景下的数据库锁定偶发错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 00:26:16