执行 cx_Freeze 结果时的循环依赖

问题描述

我面临着一个非常简单的重现问题,但我完全不明白发生了什么。

我尝试使用 cx_Freeze 编译使用 fastparquet 依赖项的 Python 脚本。当我直接使用 python script.py 启动脚本时,我能够执行它。但是如果我用 cx_Freeze 编译它,我会在 fastparquet 导入时遇到循环依赖错误。下面是一个重现问题的非常简单的案例:

script.py:

import fastparquet

setup.py:

#!/usr/bin/env python3
from cx_Freeze import setup,Executable

setup(
    name="test",executables=[Executable("script.py",base="Console",target_name="test.exe")],)

如果我直接启动 python script.py,我得到:

(test) O:\Temp\Tests\python\test_cx_Freeze>python script.py

(test) O:\Temp\Tests\python\test_cx_Freeze>

所以没什么(也没有错误),因为脚本只生成一个 import

如果我使用命令 python setup.py build 用 cx_Freeze 编译相同的脚本,然后启动 text.exe 结果,我会收到以下循环依赖错误

(test) O:\Temp\Tests\python\test_cx_Freeze\build\exe.win32-3.8>test.exe
Traceback (most recent call last):
  File "C:\Users\alexa\Envs\test\lib\site-packages\cx_Freeze\initscripts\__startup__.py",line 74,in run
    module.run()
  File "C:\Users\alexa\Envs\test\lib\site-packages\cx_Freeze\initscripts\Console.py",line 36,in run
    exec(code,m.__dict__)
  File "script.py",line 1,in <module>
  File "C:\Users\alexa\Envs\test\lib\site-packages\fastparquet\__init__.py",line 5,in <module>
    from .core import read_thrift
  File "C:\Users\alexa\Envs\test\lib\site-packages\fastparquet\core.py",line 9,in <module>
    from . import encoding
  File "C:\Users\alexa\Envs\test\lib\site-packages\fastparquet\encoding.py",line 11,in <module>
    import numba
  File "C:\Users\alexa\Envs\test\lib\site-packages\numba\__init__.py",line 19,in <module>
    from numba.core import config
  File "C:\Users\alexa\Envs\test\lib\site-packages\numba\core\config.py",line 16,in <module>
    import llvmlite.binding as ll
  File "C:\Users\alexa\Envs\test\lib\site-packages\llvmlite\binding\__init__.py",line 4,in <module>
    from .dylib import *
  File "C:\Users\alexa\Envs\test\lib\site-packages\llvmlite\binding\dylib.py",line 3,in <module>
    from llvmlite.binding import ffi
ImportError: cannot import name 'ffi' from partially initialized module 'llvmlite.binding' (most likely due to a circular import) (O:\Temp\Tests\python\test_cx_Freeze\build\exe.win32-3.8\lib\llvmlite\binding\__init__.pyc)

我检查了它似乎有什么问题:

  • llvmlite.binding 模块由 numba
  • 导入
  • 然后,llvmlite.binding 中的文件之一,尝试使用 ffi 导入子模块 from llvmlite.binding import ffi

对我来说,这不是循环依赖,因为第二次导入不是导入所有 llvmlite.binding 模块,而是只导入 llvmlite.binding.ffi

我不明白:

  • 为什么将第二次导入视为循环依赖?
  • 为什么使用 python 命令行调用我的脚本和 cx_Freeze 结果之间存在差异?是不是因为 cx_Freeze 结果用于处理依赖项的方法

解决方法

packages = ["llvmlite.binding"] 应该可以解决这个问题。

https://cx-freeze.readthedocs.io/en/latest/distutils.html#build-exe

编辑: cx_Freeze 6.6 刚刚发布,并针对此问题提供了相关信息。