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

使用importlib与cx-freeze打包后出现FileNotFound问题

解决cx-freeze打包后importlib读取包资源失败的问题

我完全懂你这种困惑——明明文件已经乖乖待在build目录的lib对应包路径下,程序却死活找不到,只有把文件扔到exe根目录才能正常运行。这其实是cx-freeze打包后,Python资源查找逻辑发生变化导致的,咱们一步步来搞定它:

问题根源

在源码环境下,importlib.resources.read_text会顺着Python的包结构精准找到资源文件,但cx-freeze打包后,运行环境和源码环境完全不一样:

  • 打包后的Python模块被放到lib目录,但程序运行时,importlib会优先从可执行文件所在的根目录解析包资源,而非lib下的子路径;
  • cx-freeze默认不会自动处理包内的非代码资源文件,哪怕你手动把文件复制到lib的对应路径,运行时的资源查找逻辑也没指向那里。

解决方案

方案1:适配打包环境的读取逻辑(简单直接)

通过判断程序是否处于打包状态,切换资源读取路径,同时调整setup.py的文件复制规则:

第一步:修改代码中的读取逻辑

import sys
import os
from importlib.resources import read_text

def read_my_text_file():
    # 判断是否是cx-freeze打包后的运行环境
    if getattr(sys, 'frozen', False):
        # 打包后,读取exe所在根目录的文件
        exe_dir = os.path.dirname(sys.executable)
        file_path = os.path.join(exe_dir, 'mytextfile.txt')
        with open(file_path, 'r', encoding='ISO-8859-1') as f:
            return f.read()
    else:
        # 源码环境下,正常读取包内资源
        return read_text('spation.w2n.utils.data', 'mytextfile.txt', encoding='ISO-8859-1')

第二步:调整setup.py的include_files配置

把资源文件直接复制到可执行文件的根目录:

setup(
    # ...其他配置项
    options={
        "build_exe": {
            "include_files": [
                ("spation\\w2n\\utils\\data\\mytextfile.txt", "mytextfile.txt")
            ]
        }
    }
)

这样不管是源码环境还是打包后的exe,都能精准读取到文件。

方案2:让cx-freeze正确处理包资源(更优雅)

如果不想破坏原有的包结构,希望资源文件跟着包走,可以通过include_package_data让cx-freeze自动管理资源文件:

第一步:添加MANIFEST.in文件

在项目根目录创建MANIFEST.in,指定要包含的资源文件:

include spation/w2n/utils/data/*.txt

第二步:修改setup.py配置

from setuptools import find_packages

setup(
    name="your_app_name",
    packages=find_packages(),
    include_package_data=True,  # 自动识别MANIFEST.in里的资源文件
    options={
        "build_exe": {
            "packages": find_packages(),
            # 无需手动指定include_files,include_package_data会自动处理
        }
    }
)

第三步:使用更稳定的资源读取API(Python 3.9+)

改用importlib.resources.files来获取资源路径,它在打包环境下的兼容性更好:

from importlib.resources import files

def read_my_text_file():
    file_path = files('spation.w2n.utils.data').joinpath('mytextfile.txt')
    with open(file_path, 'r', encoding='ISO-8859-1') as f:
        return f.read()

配置完成后,cx-freeze会把资源文件和包一起打包到lib目录,importlib也能正确找到它们。

为什么你之前的配置无效?

你尝试把文件复制到lib/spation/w2n/utils/data/目录,但cx-freeze运行时,Python的资源查找路径并没有指向这个目录下的包结构,而是默认从exe根目录解析,所以即使文件存在,程序也找不到。上面的方案要么适配了这个路径变化,要么让cx-freeze正确配置了资源的查找路径。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:12:01