Python中如何从egg文件中正确导入.so文件?
我写了一个包,用
python setup.py install
安装后会在site-package目录下得到一个.egg 的文件,然后可以在 python 中 import 这个包。
问题是,我在setup.py文件中包含了 package_data,是一个名为xxx.so的动态库文件,这个库文件在 install 之后也被正确包含进那个.egg 文件里了(把.egg 重命名成.zip 解压后可以确认)。
但是,如果只用这个.egg 文件,那么包里的一行代码
from . import xxx
就会报错
ImportError: cannot import name 'xxx'
奇怪的是,如果我重命名.zip 然后解压成文件夹,from . import xxx 就能正常加载那个动态库了。
请问熟悉 Python 的 V 友这种情况该如何解决?谢谢!
Python中如何从egg文件中正确导入.so文件?
我后来在<a target="_blank" href="http://setup.py" rel="nofollow noopener">setup.py</a>中的setup()中加入了一条zip_safe=False来生成 folder 而不是 egg,解决了问题,但不知道有没有更优雅的解决方案?
在Python中从.egg文件导入.so文件,关键在于确保.so文件能被Python解释器找到。.egg文件本质上是zip压缩包,而.so文件是编译后的二进制扩展模块,Python无法直接从压缩包中加载它们。
核心解决方案:
你需要将.so文件从.egg文件中提取出来,放到Python的模块搜索路径(如site-packages目录)中,或者将包含.so文件的.egg文件路径添加到sys.path。
具体操作步骤与代码示例:
-
检查.egg文件结构:首先,确认你的.egg文件里确实包含.so文件以及对应的
__init__.py等文件。你可以将其重命名为.zip后缀后解压查看。import zipfile egg_path = 'your_package.egg' with zipfile.ZipFile(egg_path, 'r') as z: z.printdir() # 查看内部文件列表 # 如果看到 .so 文件,例如 `package/_module.so` -
方法一:安装.egg文件(推荐)
使用easy_install(旧式)或pip直接安装.egg文件是最规范的方法。这会将文件解压到site-packages,.so文件会被放在正确位置。# 在终端中使用 pip install your_package.egg # 或者 easy_install your_package.egg安装后,即可正常导入:
import your_package # 或者 from your_package import something -
方法二:动态添加到sys.path(用于临时测试)
如果你不想安装,可以将.egg文件路径加入sys.path,Python会将其视为一个目录来查找模块。但这通常对纯.so文件无效,因为.so需要被提取。一个变通方法是模拟安装过程:import sys import zipfile import tempfile import os from pathlib import Path egg_path = Path('your_package.egg') # 创建临时目录,模拟site-packages环境 with tempfile.TemporaryDirectory() as tmpdir: # 解压.egg文件到临时目录 with zipfile.ZipFile(egg_path, 'r') as z: z.extractall(tmpdir) # 通常解压后,包目录就在临时文件夹下 # 假设包名为 'mypackage' package_path = Path(tmpdir) / 'mypackage' # 将这个路径加入sys.path,Python就能找到里面的.so了 sys.path.insert(0, str(package_path.parent)) # 现在可以尝试导入 import mypackage print(mypackage.__file__)注意:这种方法在临时目录生命周期内有效,退出程序后失效,且可能遇到路径问题。
根本建议: 优先使用pip install来安装.egg文件。
import sys
import os
sys.path.append(os.path.abspath(‘xxx.egg’)) ?
用 zipimport 引用这 so
谢谢两位!不过如果通过 pip 安装,是默认生成 folder 的,并且 path 会有所变化,所以似乎 path.append 和 zipimport 都不能同时适用两种安装方式?

