我可以使用setuptools制作一个python蛋:python setup.py bdist_egg
。理论上,我应该能够为每个已安装的包使用setup.py
文件执行此操作。是否可以将整个virtualenv
虚拟python环境封装到python egg?
我特别需要将任意数量的Python软件包打包到一个.egg
中,因为我使用的系统只接受了鸡蛋,并且每个都需要单独列出,当所需软件包的数量发生变化时,这些软件变得非常难以理解。
.egg文件只是一个.zip,其中包含名为EGG-INFO
的元数据文件夹,其名称中包含版本号。您基本上可以cd lib/python-x.y/site-packages
,然后zip -r spaghetti-0.0.1.egg
将内容压缩到spaghetti-0.0.1.egg
文件中,但您确实需要元数据
如果您很幸运,并且您没有使用入口点或其他此类高级功能的软件包,则可以在EGG-INFO
中创建一个名为site-packages
的目录,其中包含以下文件:
dependency_links.txt
entry_points.txt
not-zip-safe
PKG-INFO
requires.txt
top_level.txt
除了包含以下内容的PKG-INFO
之外,所有这些都是空的
Metadata-Version: 1.1
Name: spaghetti
Version: 0.0.1
和top_level.txt
包含你的virtualenv中的所有顶级包名,每行一个,即如果你已经安装了命名空间包zope.component
和sqlalchemy
,你的top_level.txt
应该有
zope
sqlalchemy
当然事情并不总是这么简单。对于Python 2.7上的命名空间包(zope.component
就是这种情况),有一些神奇的.pth
条目。对于这些,你需要在包中创建空的__init__.py
s,或者在EGG-INFO/namespace_packages.txt
中列出它们;在zope.component
的情况下,zope
是一个没有__init__.py
的命名空间包,所以EGG-INFO
应该有一行namespace_packages.txt
,zope
。但是,如果没有这个中间步骤,Python 3中的命名空间打包应该按原样运行。
同样,如果您需要使用入口点,则需要将所有包中egg infos的entrypoints.txt连接到egg的entrypoints.txt
中。
更正:你不能以这种方式做入口点,不管没有任何严重的黑客攻击。分发名称(在本例中为spaghetti
)将用于所有入口点而不是包名称。没有直接的方法来规避这一点。
最后,wheel
确实可以被认为是优于egg
的格式,但它们不兼容,如果可以,你应该使用wheel
来打包虚拟环境。但是,如果一个系统特别希望有一个旧的.egg
文件格式的文件,它将不适用于wheel。此外,有时不需要安装.egg
,它可以从PYTHON_PATH
使用,因为它...
出于几个原因,你不应该这样做
即使你可以设法做到这一点,它也不会像你期望的那样工作。如果用户已经安装了鸡蛋中的一个包,它们会发生冲突,因为python egg不会添加额外的命名空间。
此外,蟒蛇蛋有点出路。如果要创建二进制分发,则应使用较新的python wheels
。
如果你有一个带有依赖项的项目,只需在setup.py
中声明这些依赖项,pip就会处理它们的安装。如果您有一些PyPi上不存在的依赖项,或者您需要一个非常特定的旧版本的软件包,请将这些软件包作为子软件包包含在软件包中。
/my_package
__init__.py
/libs
__init__.py
/non_pypi_package
/legacy_package
然后在您的代码中,而不是将它们导入为
import non_pypy_package
你会用的
from my_package.libs import non_pypi_package