Python与py2exe - 隐式导入模块

3 投票
1 回答
5242 浏览
提问于 2025-04-17 11:02

我之前用过py2exe好几次,来为我的Python程序创建*.exe文件。不过这次我遇到了一个错误。我觉得我知道问题出在哪里,但不知道怎么解决。

我有几个wx.Panels放在一个子文件夹里,数量可能会变化,所以我通过一个函数来导入它们,这个函数会找到文件夹里的*.py文件,然后调用下面的函数来真正导入每个面板。

在普通的Python环境下,这样做没问题。但是,py2exe却把这些文件给漏掉了。我猜是因为这些文件没有被明确导入,所以py2exe认为它们不需要。有没有什么解决办法?py2exe里有没有我不知道的选项?

谢谢!

# module = Module to be imported (string)
# folder = Folder containing the module (string)
def import_module(module, folder=None):
   if folder is None:
      return __import__(module)
   return getattr(__import__('%s.%s' % (folder.replace(os.path.sep, '.'),
      module)), module)


...within some other function...
modules = [import_module(os.path.basename(os.path.splitext(filename)[0]), 'Panels') for filename in glob.glob('Panels//*.py')]

编辑

我在这里加一个我用过的setup.py示例脚本。不过我大概试过20种不同的变体,还有几种完全不同的脚本(都是我在网上找到的)。需要注意的是,一个要求是它必须完全包含在一个可执行文件里。

from distutils.core import setup
import py2exe

import wxversion
wxversion.select("2.8.12.1")
import wx
import wx.lib.pubsub

includes = []
excludes = ['_gtkagg', '_tkagg', 'bsddb', 'curses', 'email', 'pywin.debugger',
            'pywin.debugger.dbgcon', 'pywin.dialogs', 'tcl',
            'Tkconstants', 'Tkinter']
packages = ['wx.lib.pubsub']
dll_excludes = ['libgdk-win32-2.0-0.dll', 'libgobject-2.0-0.dll', 'tcl84.dll',
                'tk84.dll']

import glob
my_data_files = [('Panels', glob.glob('Panels/*.py'))]

setup(
    options = {"py2exe": {"compressed": 2,
                          "optimize": 2,
                          "includes": includes,
                          "excludes": excludes,
                          "packages": packages,
                          "dll_excludes": dll_excludes,
                          "bundle_files": 2,
                          "dist_dir": "dist",
                          "xref": False,
                          "skip_archive": False,
                          "ascii": False,
                          "custom_boot_script": '',
                         }
              },
    zipfile = None,
    #data_files = my_data_files,
    windows=['Main.py']
)

1 个回答

0

我觉得我找到了问题的解决办法。在我的setup.py文件里,我把'includes = []'这一行替换成了:

includes = ['Panels.%s' % os.path.basename(os.path.splitext(filename)[0]) for
        filename in glob.glob('Panels//*.py')]

在我的代码中,我使用'import_module'函数时,之前是用一个通配符来导入Panels目录里的模块。现在,我直接写了一个模块的列表来包含它们。

这虽然不是我想要的完美解决方案(我不想把面板的列表写死),但看起来是有效的。除非我发现更好的办法,不然我就继续用这个。

撰写回答