python打包numpy和pandas报错-numpy: Error importing numpy: you should not try to import numpy from its source directory

在使用numpy2.3.2版本和python3.12版本时,打包一直报错

numpy: Error importing numpy: you should not try to import numpy from its source directory;
please exit the numpy source tree, and relaunch your python interpreter from there.

网上很多说是版本不匹配的问题,但是都没说这两个版本是否匹配。  

 

通过PyInstaller 的钩子(hooks)来精确地收集 numpypandas 的所有动态链接库和数据文件。

修改 .spec 文件,强制收集所有必需的二进制文件:

# -*- mode: python ; coding: utf-8 -*-

from PyInstaller.utils.hooks import collect_all, collect_data_files, collect_dynamic_libs

block_cipher = None

# --- 关键修改:为 numpy 和 pandas 收集所有文件 ---
datas_n, binaries_n, hiddenimports_n = collect_all('numpy')
datas_p, binaries_p, hiddenimports_p = collect_all('pandas')

a = Analysis(
    ['watermark_tool.py'],
    pathex=[],
    # --- 关键修改:合并二进制文件 ---
    binaries=binaries_n + binaries_p,
    # --- 关键修改:合并数据文件 ---
    datas=[
        ('示例数据.xlsx', '.'),
        *datas_n, # numpy 的数据文件
        *datas_p, # pandas 的数据文件
    ],
    # --- 关键修改:合并隐藏导入 ---
    hiddenimports=list(set(
        [
            'numpy',
            'pandas',
            'PIL',
            'PIL.Image',
            'PIL.ImageFont',
            'PIL.ImageDraw',
            'openpyxl',
            'tkinter',
            'tkinter.ttk',
            'tkinter.messagebox',
            'tkinter.filedialog',
            'json',
            'datetime',
            'threading',
            'platform',
            'os',
            'sys',
        ] + hiddenimports_n + hiddenimports_p # 添加 numpy 和 pandas 的隐藏导入
    )),
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    excludes=[
        'matplotlib',
        'scipy',
        'PyQt5',
        'PyQt6',
        'PySide2',
        'PySide6',
    ],
    win_no_prefer_redirects=False,
    win_private_assemblies=False,
    cipher=block_cipher,
    noarchive=False,
)

pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)

exe = EXE(
    pyz,
    a.scripts,
    a.binaries,
    a.zipfiles,
    a.datas,
    [],
    name='水印工具',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    upx_exclude=[],
    runtime_tmpdir=None,
    console=False, # 设置为 False 以隐藏控制台窗口
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
)

  打包日志非常长,但是可以看到大量的如下分析行

INFO: Analyzing hidden import 'pandas.tests.tseries.offsets.test_business_day'
INFO: Analyzing hidden import 'pandas.tests.series.test_arithmetic'
INFO: Analyzing hidden import 'pandas.tests.plotting.frame.test_frame_subplots'
...
INFO: Analyzing hidden import 'numpy.lib.tests.test_polynomial'
INFO: Analyzing hidden import 'numpy.polynomial.tests.test_classes'
...

  

这表明 PyInstaller 正在尝试分析并打包 pandasnumpy 库中所有的测试模块(pandas.tests.*numpy.*.tests.*)。这些测试模块通常依赖于 pytest 等测试框架,而这些框架在您的生产环境中并未安装,因此 PyInstaller 会抛出 ModuleNotFoundError: No module named 'pytest' 的警告。

 

更重要的是,这些测试模块是完全不需要打包到最终的生产应用程序中的。它们不仅体积庞大,而且会引入不必要的依赖和潜在的冲突,这就是导致最终的可执行文件在运行时无法正确加载 numpy 核心库的根本原因。

 

解决方案:在 .spec 文件中排除测试模块,excludes 参数修改为如下内容:

excludes=[
    'matplotlib',
    'scipy',
    'PyQt5',
    'PyQt6',
    'PySide2',
    'PySide6',
    # --- 关键添加:排除测试模块 ---
    'pytest',  # 排除 pytest 本身
    'unittest', # 可选,排除标准库 unittest,进一步减小体积
    'pandas.tests', # 排除所有 pandas 测试
    'numpy.testing', # 排除 numpy 的测试工具
    'numpy._pytesttester', # 排除 numpy 的 pytest 测试器
    'numpy.f2py.tests', # 排除 f2py 测试
    'numpy.core.tests', # 排除核心测试
    'numpy.lib.tests', # 排除 lib 测试
    'numpy.linalg.tests', # 排除线性代数测试
    'numpy.ma.tests', # 排除 masked array 测试
    'numpy.matrixlib.tests', # 排除 matrix 测试
    'numpy.polynomial.tests', # 排除多项式测试
    'numpy.random.tests', # 排除随机数测试
    'numpy.fft.tests', # 排除傅里叶变换测试
    'numpy.typing.tests', # 排除类型提示测试
],

  再次打包即可,当然可以直接就添加test排除,hook是为了找到报错原因。

 

posted @ 2025-09-09 09:11  聪聪知道  阅读(303)  评论(0)    收藏  举报