如何使用distutils创建可执行的.zip文件?
从Python 2.6开始,如果一个.zip文件里有一个叫做__main__.py
的文件在最上面,Python就可以直接运行这个.zip文件。我想利用这个功能,提供我正在开发的工具的预览版本,这样用户只需要把.zip文件复制到他们的电脑上,就可以使用,不需要安装其他东西。请问有没有标准的方法来创建这样的.zip文件?我希望这个方法能在Python 2.6和2.7上都能用。
理想情况下,我想使用distutils,因为我在进行正常安装时已经成功使用过它。有没有一种标准的方法可以使用(或扩展)distutils来创建这样的.zip文件呢?
distutils提供了一个sdist
命令,可以创建一个源代码分发包,这个包几乎是正确的,但它的结构有点太复杂了。
比如说,我的源代码树是这样的:
my_package/
- setup.py
- src/
- __main__.py
- module1/
- module2/
- module3/
当我运行python setup.py sdist
时,最终得到的.zip文件结构是这样的:
my_package-0.1.zip
- my_package-0.1/
- README.txt
- PKG_INFO
- src/
- __main__.py
- module1/
- module2/
- module3/
这个文件不能直接执行,因为__main__.py
不在分发包的最上面。实际上,我想要的是一个源代码分发包,但不包含src
这个文件夹,只包含src
文件夹下的文件。或者说,正好是sdist
给我的结构,但在压缩包的最上面多一个__main__.py
文件。
2 个回答
你可以通过把一个叫做 __main__.py
的文件放到你的 .zip 文件的根目录下,让 sdist
也变得可以执行。
import os
import sys
# add package .zip to python lookup path
__dir__ = os.path.dirname(__file__)
path = os.path.join(__dir__, 'my_package-0.1', 'src')
sys.path.insert(0, path)
import module1
module1.main()
这样做会把压缩包中的源代码子目录添加到 sys.path
中,这样就可以从 module1
中导入内容了。
我现在不能告诉你怎么修改 distutils 的 sdist
命令,让它自动把这个 __main__.py
文件放进 .zip
里,但这确实是可行的。
更新: 因为 setup.cfg
是全局的,所以它会影响所有命令的 'install-lib' 设置,这并不是我们想要的。不幸的是,按照我所知,无法通过命令行将选项传递给子命令。例如,如果你指定 bdist --install-lib=/
,它会报错,而不是将这个选项传递给子命令。
如果你想在运行 bdist
时,仅仅为 install
子命令自定义 install-lib
,你可以通过创建一个 bdist_dumb
命令的子类,并在构造/重新初始化 install
子命令后手动设置路径来实现:
setup.py
from distutils.core import setup
from distutils.command.bdist_dumb import bdist_dumb
class custom_bdist_dumb(bdist_dumb):
def reinitialize_command(self, name, **kw):
cmd = bdist_dumb.reinitialize_command(self, name, **kw)
if name == 'install':
cmd.install_lib = '/'
return cmd
if __name__ == '__main__':
setup(
# our custom class override
cmdclass = {'bdist_dumb': custom_bdist_dumb},
name='my_package',
py_modules = ['__main__'],
packages = ['module1', 'module2'],
package_dir = {'': 'src'}
)
运行:
% python setup.py bdist --format=zip
% unzip -l dist/my_package-0.0.0.linux-x86_64.zip
Archive: dist/my_package-0.0.0.linux-x86_64.zip
Length Date Time Name
--------- ---------- ----- ----
184 2011-05-31 20:34 my_package-0.0.0.egg-info
30 2011-05-31 20:34 __main__.py
128 2011-05-31 20:34 __main__.pyc
107 2011-05-31 20:34 module1/__init__.pyc
0 2011-05-31 20:27 module1/__init__.py
107 2011-05-31 20:34 module2/__init__.pyc
0 2011-05-31 20:27 module2/__init__.py
--------- -------
556 7 files
% python dist/my_package-0.0.0.linux-x86_64.zip
my_package working.