如何打包命令行应用程序以供分发?

7 投票
2 回答
2174 浏览
提问于 2025-04-18 09:17

我现在正在用Python写一个命令行应用程序,想让最终用户下载和运行起来非常简单。对于那些在Windows上可能没有安装Python(2.7)的人,我打算使用PyInstaller来生成一个独立的Windows可执行文件。这样用户只需下载“myapp.exe”,然后运行myapp.exe [参数]就可以了。

我还想为已经安装了Python的用户(在不同平台上)提供一个(更小的)下载选项。一个选择是把我的所有代码放到一个单独的.py文件中,命名为“myapp.py”(文件开头加上#! /usr/bin/env python),然后提供这个文件。用户可以下载这个文件,然后用myapp.py [参数]或者python myapp.py [参数]来运行。不过,把我的应用限制在一个.py文件里有几个缺点,比如限制了我组织代码的能力,也让使用第三方依赖变得困难。

所以我想分发几个我自己代码的文件,还有一些(纯Python的)依赖库。有没有什么工具可以把这些打包成一个单独的文件,方便用户下载并用已有的Python安装来运行呢?

编辑:请注意,我需要这些应用程序对最终用户来说容易运行。他们可能没有安装pip,也没有其他任何Python核心以外的东西。使用PyInstaller,我可以生成一个文件,用户可以从网上下载并用一个命令运行(或者如果没有参数,只需双击即可)。有没有办法在不使用PyInstaller的情况下实现这种易用性(也就是说,不重复打包Python运行环境)呢?

2 个回答

5

你可以按照评论里的建议使用pip。为了让你的项目可以被安装,你需要创建一个 MANIFEST.in 文件和一个 setup.py 文件。你还可以添加一些模块作为前置条件。想了解更多信息,可以查看这个问题(虽然不是专门针对Django的):

如何打包一个Python应用程序,使其可以通过pip安装?

这样一来,你的模块就可以在Python中使用了。用户可以通过运行一个文件来使用你的模块,方法有几种,比如 python path/run.py./path/run.py(需要有 +x 权限),或者 python -c "这里写一些代码"(比如用来设置别名)。

你甚至可以让用户从一个公共的git仓库安装,像这样:

pip install git+https://bitbucket.org/yourname/projectname.git

...在这种情况下,他们也需要安装git。

7

我不太喜欢把所有东西放在一个文件里的做法,因为这样会让维护变得很麻烦。我会考虑下面这种方法。

我现在非常喜欢使用Python的虚拟环境,因为它可以把你的应用程序所需的依赖包和操作系统的安装隔离开来。想象一下,如果你现在要发布的应用程序使用的是一个叫做requests v1.0的Python包。过了一段时间后,你又创建了一个新的应用程序,这个应用程序需要用到requests v2.3。如果你想在同一台电脑上同时安装这两个应用,就可能会出现版本冲突的问题。虚拟环境可以解决这个问题,因为每个应用都有自己的包存放位置。

创建一个虚拟环境很简单。一旦你安装了virtualenv,只需要运行,比如说virtualenv /opt/application/env。这样,你就为你的应用创建了一个独立的Python环境。此外,虚拟环境也很容易清理,只需删除env目录就可以了。

你需要一个setup.py文件来把你的应用安装到这个环境里。假设你的应用使用的是requests v2.3.0,你的自定义代码放在一个叫做acme的包里,而你的脚本叫做phone_home。你的目录结构大概是这样的:

acme/
    __init__.py
    models.py
    actions.py
scripts/
    phone_home
setup.py

你的setup.py文件大概是这样的:

from distutils.core import setup


install_requires = [
    'requests==2.3.0',
]

setup(name='phone_home',
      version='0.0.1',
      description='Sample application to phone home',
      author='John Doe',
      author_email='john@doe.com',
      packages=['acme'],
      scripts=['scripts/phone_home'],
      url='http://acme.com/phone_home',
      install_requires=install_requires,
)

现在,你可以把你的项目打包成一个tar包,然后随便选择一个地方来托管(比如自己的网页服务器、S3等):

tar cvzf phone_home-0.0.1.tar.gz .

最后,你可以用pip把你的包安装到你创建的虚拟环境里:

/opt/application/env/bin/pip install http://acme.com/phone_home-0.0.1.tar.gz

然后你可以用下面的命令来运行phone_home

/opt/application/env/bin/phone_home

或者在/usr/local/bin里创建一个符号链接,这样你就可以直接用phone_home来调用这个脚本:

ln -s /opt/application/env/bin/phone_home /usr/local/bin/phone_home

以上所有步骤都可以放在一个shell脚本里,这样就可以通过一个命令来完成安装。

稍微修改一下,这种方法在开发环境中也非常好用;也就是说,可以用pip来安装或引用你的开发目录:pip install -e .,其中.代表当前目录,你应该在包含setup.py的项目目录下。

希望这对你有帮助!

撰写回答