py2exe: 排除一个想导入所有部分的包的部分

3 投票
2 回答
1241 浏览
提问于 2025-04-18 13:20

我正在尝试使用py2exe来打包我的程序,并且想尽量减少使用的第三方库。我希望只包含一个大第三方包中必要的小部分,但我不知道怎么做才能避免在运行时调用这个包的__init__.py文件,因为它会导入很多我不想要的内容。

下面是我的情况总结:

myscript.py:   from BigPackage.SmallSubset import TheOnlyFunctionIReallyNeed

BigPackage/__init__.py:            import SmallSubset, HugeUnwantedSubset
BigPackage/SmallSubset.py:         import AcceptableDependencies
BigPackage/HugeUnwantedSubset.py:  import UnacceptablyHugeDependencies

问题是,即使我成功地包含了BigPackage的一些部分,但当在运行时调用import BigPackage.SmallSubset时,BigPackage/__init__.py会先运行,这样它就会尝试导入那些我不想要的部分,从而导致错误。如果我能让py2exe只包含BigPackage/SmallSubset.py而不包含BigPackage/__init__.py,那就好了,但我一直没能让py2exe理解这个想法。我在我的setup.py文件中尝试了以下几种方法:

import BigPackage     # let's try a Deny/Allow approach:
options[ 'py2exe' ][ 'excludes' ].append( 'BigPackage' )
options[ 'py2exe' ][ 'includes' ].append( 'BigPackage.SmallSubset' )
# nope, py2exe fails with 'ImportError: No module named BigPackage' in py2exe/mf.py

...还有:

import BigPackage     # this seems less plausible, but worth a try:
options[ 'py2exe' ][ 'excludes' ].append( 'BigPackage.__init__' )
# nope, __init__.pyc still turns up in dist

...还有:

import BigPackage     # really getting desperate now:
options[ 'py2exe' ][ 'excludes' ].append( BigPackage.__file__ )
# nope, __init__.pyc still turns up in dist

...但都没有成功。有人知道怎么解决这个问题吗?

2 个回答

0

你想要的这个功能,如果不对BigPackage库进行修改,是不可能实现的。

0

所有的解决方案看起来都不太靠谱(可以看看问题下的评论)。不过,我最后决定不去修改 __init__.py,而是采用了一个新的方法:我会进去把我需要的特定内容提取出来,然后复制到临时文件中。

import sys, os, shutil

# awkward kludge to include BigPackage.SmallSubset by hand without having to include the rest of BigPackage
src = [ os.path.join( x, 'BigPackage', 'SmallSubset.py' ) for x in sys.path ]
src = [ x for x in src if os.path.isfile( x ) ][ 0 ]
shutil.copyfile( src, 'BigPackageSmallSubset.py' )
import BigPackageSmallSubset


options = { 'py2exe': { 'excludes' : [ 'BigPackage' ], 'includes' : [ 'BigPackageSmallSubset' ], 'compressed' : True, }, }

# setup( ..., options=options, ... )

os.remove( 'BigPackageSmallSubset.py' )
os.remove( 'BigPackageSmallSubset.pyc' )

接着,我让 myscript.py 能够适应可能出现的不同情况:

try: from BigPackage.SmallSubset import TheOnlyFunctionIReallyNeed
except ImportError: from BigPackageSmallSubset import TheOnlyFunctionIReallyNeed

撰写回答