如何使用distutils创建可执行的.zip文件?

时间:2011-05-31 21:52:15

标签: python distutils python-2.6

如果zip文件在zip存档的顶部包含__main__.py文件,则Python 2.6及更高版本能够直接执行.zip文件。我想利用此功能提供我正在开发的工具的预览版本,除了将.zip文件复制到磁盘之外,不需要用户安装任何东西。有没有标准的方法来创建这样的zip文件?我正在寻找一个适用于python 2.6和python 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发行版,而只包含src下的文件。那个,或者恰恰是sdist给我的,但是在档案的顶部有一个额外的__main__.py

2 个答案:

答案 0 :(得分:4)

已更新:由于setup.cfg是全局的,因此会影响所有命令的“install-lib”设置,这不是所需的。不幸的是(据我所知)没有办法通过命令行将选项传递给子命令,例如如果指定bdist --install-lib=/,则会引发错误,而不是将其传递给子命令。

要在运行install-lib时自定义install子命令 bdist,您可以继承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.

答案 1 :(得分:1)

通过将以下sdist文件放在.zip的根目录下,也可以使__main__.py可执行:

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,但这绝对是真的。