【问题标题】:cx_freeze - including my own modules?cx_freeze - 包括我自己的模块?
【发布时间】:2014-12-16 01:19:25
【问题描述】:

我有一个使用 PyQt4 构建的小型应用程序,我正在尝试使用 cx_freeze 冻结它,但我遇到了 cx_freeze 问题,包括我自己的一些应用程序运行所需的模块。

我的应用程序中导入了两个模块,它们位于应用程序所在的上方文件夹中。即:

应用路径:

Python\DataViewer-PyQt4\DataViewer.py

其他模块:

Python\我的分析包\Ephystools

Python\我的分析包\PrairieAnalysis

在我的应用程序中,我使用导入这些(如果它们不在我的 python 路径中)

sys.path.append(os.path.abspath('../My Analysis Packages'))

我已尝试在 setup.py 文件的“包含”和“包”中包含 PrairieAnalysis 和 EphysTools。我也尝试过包含“我的分析包”。我也尝试过提供这些路径。

它们都包含 init.py 文件,因为实际应用程序能够很好地导入它们。

如果我将 PrairieAnalysis 和/或 EphysTools 放在“包含”列表中,那么 setup.py build 会返回 ImportError:

 File "C:\Anaconda3\lib\site-packages\cx_Freeze\finder.py", line 386, in _ImportModule
    raise ImportError("No module named %r" % name)
ImportError: No module named 'PrairieAnalysis'

如果我将它们排除在“包含”之外,setup.py 构建完成,但是当我打开应用程序时,我会遇到同样的错误。

我查看了各种 cx_freeze 模块导入问题,但似乎都没有处理过这种特殊情况。

我的实际 setup.py:

# -*- coding: utf-8 -*-

import sys
from cx_Freeze import setup, Executable

base = None
if sys.platform == 'win32':
    base = 'Win32GUI'

options = {
    'build_exe': {
        'includes': ['atexit', 'PrairieAnalysis', 'EphysTools'],
    }
}

executables = [
    Executable('DataViewer.py', base=base)
]

setup(name='DataViewer',
      version='0.1',
      description='Application for viewing Prairie-generated csv data files',
      options=options,
      executables=executables
      )

编辑 1: setup.py 文件中 os.getcwd() 的输出:

D:\OneDrive\Documents\Python\DataViewer-PyQt4

setup.py 文件中 sys.path 的输出:

    ['D:\\OneDrive\\Documents\\Python\\DataViewer-PyQt4', 'D:\\OneDrive\\Documents\\Python\\My Analysis Packages', 'C:\\Anac
    onda3\\python34.zip', 'C:\\Anaconda3\\DLLs', 'C:\\Anaconda3\\lib', 'C:\\Anaconda3', 'C:\\Anaconda3\\lib\\site-packages',
     'C:\\Anaconda3\\lib\\site-packages\\Sphinx-1.2.3-py3.4.egg', 'C:\\Anaconda3\\lib\\site-packages\\win32', 'C:\\Anaconda3
    \\lib\\site-packages\\win32\\lib', 'C:\\Anaconda3\\lib\\site-packages\\Pythonwin', 'C:\\Anaconda3\\lib\\site-packages\\r
    unipy-0.1.1-py3.4.egg', 'C:\\Anaconda3\\lib\\site-packages\\setuptools-7.0-py3.4.egg']

编辑2:

所以我也尝试过使用 py2exe,但遇到了同样的问题。如果我在“包含”中包含这些包,我会得到以下回溯:

Traceback (most recent call last):
  File "setup.py", line 7, in <module>
    setup(windows=['DataViewer.py'], options={"py2exe": {"includes" :["sip", "PyQt4.QtCore", "PyQt4.QtGui", "PrairieAnal
ysis", "EphysTools"]}})
  File "C:\Anaconda3\lib\distutils\core.py", line 148, in setup
    dist.run_commands()
  File "C:\Anaconda3\lib\distutils\dist.py", line 955, in run_commands
    self.run_command(cmd)
  File "C:\Anaconda3\lib\distutils\dist.py", line 974, in run_command
    cmd_obj.run()
  File "C:\Anaconda3\lib\site-packages\py2exe\distutils_buildexe.py", line 188, in run
    self._run()
  File "C:\Anaconda3\lib\site-packages\py2exe\distutils_buildexe.py", line 267, in _run
    builder.analyze()
  File "C:\Anaconda3\lib\site-packages\py2exe\runtime.py", line 164, in analyze
    mf.import_hook(modname)
  File "C:\Anaconda3\lib\site-packages\py2exe\mf3.py", line 120, in import_hook
    module = self._gcd_import(name)
  File "C:\Anaconda3\lib\site-packages\py2exe\mf3.py", line 274, in _gcd_import
    return self._find_and_load(name)
  File "C:\Anaconda3\lib\site-packages\py2exe\mf3.py", line 318, in _find_and_load
    loader = importlib.find_loader(name, path)
  File "C:\Anaconda3\lib\importlib\__init__.py", line 87, in find_loader
    name=name)
ImportError: namespace packages do not have loaders

在这种情况下,我将我的两个包(PrairieAnalysis 和 EphysTools)放入我的站点包文件夹中。为什么我的包裹的处理方式与其他包裹不同?

编辑 3: 所以我使用以下安装脚本让 py2exe 工作:

from distutils.core import setup
import py2exe
import PrairieAnalysis.pv_import
import EphysTools.utilities

includes = ["sip", "PyQt4.QtCore", "PyQt4.QtGui", "PrairieAnalysis", "EphysTools", "lxml._elementpath"]
packages = ["PrairieAnalysis", "EphysTools"]

setup(windows=['DataViewer.py'], options={"py2exe": {"includes" : includes,
                                                     "packages": packages}})

仅仅导入 PrairieAnalysis 和 EphysTools 并没有工作,也没有做

from PrairieAnalysis import *
from EphysTools import *

但是,将这些导入语句添加到我的 cx_freeze setup.py 脚本并不能解决问题。

编辑 4:

>>> import PrairieAnalysis
>>> print(PrairieAnalysis.__file__)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute '__file__'
>>> print(PrairieAnalysis.__init__)
<method-wrapper '__init__' of module object at 0x0000000002B9C9F8>

编辑 5:

>>> os.listdir('D:\\OneDrive\\Documents\\Python\\My Analysis Packages')
['.idea', 'EphysTools', 'PrairieAnalysis', '__init___.py']
>>> os.listdir('D:\\OneDrive\\Documents\\Python\\My Analysis Packages\\PrairieAnalysis')
['misc_code.py', 'pv_import.py', 'pxml_parse.py', '__init___.py', '__pycache__']
>>> os.listdir('D:\\OneDrive\\Documents\\Python\\My Analysis Packages\\EphysTools')
['synaptics.py', 'utilities.py', '__init___.py', '__pycache__']

【问题讨论】:

    标签: python py2exe importerror cx-freeze


    【解决方案1】:

    您需要在 setup.py 脚本中修改 sys.path,方法与在应用程序中相同。 cx_Freeze 查看 sys.path 以查找要包含在构建中的模块和包,因此如果包含这些包的目录不在 sys.path 上,则找不到它们。

    编辑:原来问题是一个错误命名的__init__.py 文件。该包仍可作为 PEP 420 命名空间包导入,但 cx_Freeze 尚未处理这些。

    【讨论】:

    • 这是我的第一个想法,但这样做并没有解决问题。
    • 事实上,sys.path 行实际上在 try..except 块中,因为在我进行大部分编码的计算机上,我实际上默认包含“我的分析包”我的 python 路径,因为我经常使用这些模块。 sys.path.append 行仅包含在应用程序中,以防我在我没有进行更改以确保这些模块始终可用于导入的其他计算机上工作
    • 您能否在调用 setup() 之前让您的 setup.py 脚本打印 os.getcwd()sys.path,并检查它是否正在寻找您认为寻找这些软件包的位置?
    • 完成,请参阅我在问题中的编辑以了解这些返回的内容。包含 PrairieAnalysis 和 EphysTools 的正确路径位于 sys.path 中。我还尝试将 PrairieAnalysis 和 EphysTools 放入我的站点包文件夹中。这样做我可以从我机器上的任何地方(终端、另一个脚本等)很好地导入它们,但它们仍然没有被复制/我得到一个 ImportError。真的不知道这里发生了什么。除了 init 之外还有什么东西需要放在模块文件夹中吗?
    • 我什至可以将 import PrairieAnalysis 和 import EphysTools 放在实际的 setup.py 文件中。这不会产生 ImportError(如果我没有将其中任何一个放入包含中,setup.py 就会运行,但两者都不会被复制并运行 DataViewer.exe 然后给出上面讨论的回溯)
    【解决方案2】:

    这可能对某人有用,我遇到了同样的问题,试图添加我自己的模块,所以最后,我做了如下:

    关于文件 setup.py:

    from cx_Freeze import setup, Executable
    files = {"include_files": ["folder/MyOwnModule1",
                           "folder/MyOwnModule2",
                           ], "packages": ["numpy", "tkinter"]}
    
    setup(
     name="My Program",
     version="4.0.0",
     description="A super cool explanation",
     options={'build_exe': files},
     executables=[Executable("Version4.0.0/main.py", base=None)])
    

    然后在终端执行:

    python setup.py build
    

    希望对你有帮助。

    【讨论】:

    • 这对我不起作用... cx_Freeze 仍然找不到我的模块。不过我不明白,您没有在packages 下写模块名称。这是故意的吗?
    • 是的,我是故意这样做的,否则它不起作用。另一种方法是使用 datadir 来定位模块,如下所示:cx-freeze.readthedocs.io/en/latest/faq.html
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-29
    • 2019-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多