2019年Python生态系统中比较流行的主题之一是关于打包和分发的。随着这一年的结束,我想总结一下我们目前可用来分发用Python构建的应用程序的多种途径。虽然其中一些也适用于任何语言。

无论你交付的是可执行文件、虚拟环境、打包的代码还是完整的应用程序,下面的列表都包括了标准系统和一些在进入2020年时需要记住的新事物。

应用程序

要发布一个应用程序,你需要的不仅仅是一个从PyPI进行pip-install的库。你需要一种万无一失的在所有支持的操作系统中安装它及其依赖项的方式。这些依赖项可以包括其他非Python包以及像二进制文件或映像之类的外部资源。

下面是一些帮助你跨平台安装和分发代码的选项。

Docker

Docker使用操作系统中的基本功能来隔离进程,使其不知道系统的其余部分。它可以在你的主机内运行不同操作系统的内核进程,非常类似于虚拟化,但不使用虚拟硬件。

它的文件系统是分层的,因此占用的空间很小,只包含运行所需的文件,而不是典型的虚拟磁盘,虚拟机中还包括空闲空间。

使用一个最小程度打包的根文件系统,我们会看到整个操作系统的映像只占用几十MB,而不是虚拟机所需的GB,这并不少见。

你可以在一个公共注册中心(如DockerHub)或你的组织内部的一个私有注册中心分发这些容器。用户会在自己的计算机上安装Docker守护进程,然后使用它来获取你的映像并在本地运行它。

由于Docker映像只不过是一个根文件系统,所以你也可以将它们作为一个文件分发,并使用Docker导入它。

要构建一个映像,你可以从一个rootfs开始,或者在一个现有的注册表映像的基础上进行添加。大多数操作系统供应商在DockerHub中都维护了官方的精简映像,这些映像通常都很小。

其他组织也为他们的应用程序的新版本制作了官方映像,比如构建在Debian之上的Python映像。Postgress、MySQL、Redis、Nginx和许多其他标准服务也都是这样做的。

Docker现在可以在Linux、OSX和Windows上运行。这种跨平台支持意味着你构建的任何映像都具有广泛的分布,并且复杂性最小。你不仅可以控制应用程序,还可以控制它所运行的环境,从而使兼容性问题变得不那么严重。

然而,在配置网络或持续性存储时仍然可能存在复杂性。典型的应用程序只需要处理端口转发,但是有时候我们很难想象抽象层是如何工作的,所以编写良好的文档依然很重要。

使用Docker,你可以控制Python发行版、支持的OS包(如各个模块所需的C库)和你的虚拟环境。

由于启动一个容器只需要几毫秒的时间,所以每次当你想要执行应用程序时运行一个新的容器是完全可以接受的,甚至是推荐的。

有些人甚至使用Docker作为虚拟环境的替代品。由于它启动很快,并且可以提供一个交互式shell,所以当你需要处理一个特定的项目时,创建一个新容器并不是一个坏主意。

一旦你有了一个配置了基础环境的运行容器,你就可以保存该映像以便重用,或者甚至可以将其导出到文件中。

例如,下面的命令会启动一个新的Python容器,将当前工作目录挂载为/work,并将你放入一个bash shell中。容器目录中的更改反映在基础目录中。

一旦进入容器,你就可以安装任何需要的Apt或PyPI包。

退出shell后你将会返回到主机。此时,你可以运行下一条命令将任何的更改保存为一个新的Docker映像,你可以稍后重用它或将其推送到DockerHub进行分发:

你可以在你组织内部的私有Docker 注册表中共享此新映像,或者运行以下命令将该容器导出为一个文件,任何人都可以下载它并将其导入他们的本地Docker环境中:

然而,分发的真正工作流程是创建一个Dockerfile,任何人都可以使用它来创建自己的映像。换句话说,你提供了一个带有Docker守护进程指令的小型文本文件,而不是整个文件系统的副本。

任何人都可以使用该文件克隆你的repo,并运行此命令去创建一个此映像的本地版本:

一个典型的Dockerfile如下所示,请查看他们的文档以获取更多信息:

更过详情:https://docs.docker.com/

虚拟机和Vagrant

容器的下一步是分发一个完整的虚拟机。自从虚拟化得到广泛应用和硬件支持以来,这种类型的系统已经存在了一段时间了。

交付一个“虚拟设备”是很有吸引力的,因为你几乎可以完全控制你的应用程序运行的环境。所有东西都是可配置的:操作系统、它的包、磁盘和网络,甚至空闲空间的大小。

使用虚拟机的缺点是发行版的大小,通常是在GB级。另外,你还得想办法让客户得到你的映像。Amazon S3 或 Digital Ocean Spaces之类的东西就是一个很好的起点。

一开始,只有服务器硬件支持运行虚拟机,但是现在每个处理器都有这个能力,而且所有主要的操作系统都支持它。还有一些免费的应用程序可以帮助你管理和配置虚拟机,比如Oracle的VirtualBox。

Vagrant是在VirtualBox等管理器上配置和运行虚拟机的另一个系统。它的功能很像Docker,你可以在一个文件中指定虚拟机所需要的所有东西,它可以为你构建和运行该虚拟机。

与前一节中的Dockerfile类似,Hashicorp的Vagrant使用一个Vagrantfile,其中包含有关如何启动和配置虚拟机的指令。

就像Docker映像提供了运行容器的基本文件系统一样,Vagrant box也为虚拟机提供了基础文件系统。

下面的示例Vagrantfile与上一节中的Dockerfile所做的事情类似:

使用这个文件克隆你的存储库,并运行这些命令来启动VM,然后你就会进入它的shell:

Vagrant确实通过使用Vagrant Box catalog提供与DockerHub类似的体验来帮助我们解决分发问题。

有了它,你可以得到你的基础映像或上传新的映像与他人分享。你甚至可以将一个Vagrantfile指向内部的URL去下载一个box。

更多详情:https://www.vagrantup.com/intro/index.html

PyInstaller

我们之前已经介绍过这个模块。PyInstaller负责绑定运行你的应用程序所需的所有资源,包括Python发行版。在爬取你的代码时,它会指出要打包哪些Python依赖项,同时仍然允许你指定其它要包括在bundle中的资源。

它的打包结果是一个适用于Windows、Linux或OSX的可安装应用程序。在执行期间,它会将该程序与绑定的解释器一起解压到一个文件夹中,并运行你的入口点脚本。

它足够灵活,可以让你控制Python发行版和执行环境。我甚至成功地使用它将浏览器与我的Python包绑定在一起。

但使用它确实会带来麻烦。在提取自身时,它将更改应用程序运行的基本目录。这意味着,任何依赖__file__来确定当前执行路径的代码现在都需要使用PyInstaller配置的内部环境。

分发你的bundle完全取决于你。对于这种类型的设置,大多数人选择对象存储和CDN。

在以这种方式分发时要记住一点,即检查你的代码是否需要验证它所运行的操作系统环境。

换句话说,与使用Docker或Vagrant不同,如果你需要安装特定的apt包,那你就无法保证该包在执行期间就已经存在。

更多详情:https://www.pyinstaller.org/

Briefcase

Briefcase是这类产品的后起之秀。它是Beeware项目的一部分,该项目旨在将Python应用程序打包分发给所有操作系统和设备,包括Android和iOS。

它与PyInstaller处于类似的领域,这意味着它可以将你的模块及其依赖项绑定到一个可安装的应用程序中。但它也增加了对移动设备和带有AppleTV或tvOS的电视的支持。

不幸的是,其文档仍然有点松散,而且主要是以示例的形式。然而,该项目很有前景,并且仍在积极开发中。颇受欢迎的编辑器Mu就将它用于打包。

你可以将使用Briefcase构建的应用程序提交到Android和Apple应用商店进行分发。

更多详情:https://beeware.org/project/projects/tools/briefcase/

虚拟环境

有时,我们可以假设你的用户拥有一个标准的操作系统。也许他们都是从公司内部的IT部门构建的库存映像运行的。也许你的应用程序很简单,根本不必担心操作系统或解释器的复杂性。

如果你只需要考虑Python代码及其依赖关库,那么这个类别适合你。

Pex

Pex是由Twitter的员工构建的,它是一种将整个虚拟环境与你的Python应用程序一起发布的方法。它被设计为使用一个预先安装的Python解释器,它利用了为Python Zip应用程序构建的标准(在PEP-441中有概述)。

从Python 2.6开始,解释器就能够将目录或zip格式的归档文件作为脚本执行。

Pex构建在此基础之上,简化了复制单个文件的分发过程。这些文件可以在不同的平台(OSX、Linux、Windows)以及不同的解释器上工作。尽管在使用带有C绑定的模块时存在一些限制。

在你的基本系统中安装Pex之后,你可以使用它生成一个包含整个Python环境的文件。

将该文件传递到你同事的计算机,你将能够在那里执行该文件,而不需要安装除基本Python解释器之外的任何东西。

你甚至可以在解释器模式下运行一个文件,这样它就会打开一个Python REPL,其中包含你的环境中可以导入的所有必要模块。

将你的虚拟环境冻结为一个.pex文件相当简单:

然后你可以执行该文件来打开一个带有你的环境的REPL:

你还可以在创建文件时指定入口点,以便它可以在你的模块中执行特定的函数,就像你直接运行python命令一样。

目前没有系统可以为你分发Pex文件,因此,就像前面的项目一样,你只能使用公共对象存储和CDNs。

更多详情:https://github.com/pantsbuild/pex

Shiv

与Pex类似,LinkedIn的人员建立了一个不同的模块,称为Shiv。他们构建一些不同的东西的主要原因是试图在Pex可执行文件的开始期间尝试并解决一个问题。考虑到存储库和依赖项的复杂性,他们希望以不同的方式处理环境设置。

代替将各种轮子与应用程序一起打包,Shiv会包含一个完整的由pip安装的site-packages目录。这让所有的东西都能开箱即用,并且速度几乎是Pex的两倍。

这里是一个如何使用Shiv生成一个.pyz文件的例子,它做了一些与Pex部分类似的事情:

然后,你就可以使用以下命令直接执行它:

需要注意的是,打包带有OS依赖项的库在平台之间是不交叉兼容的。正如在Pex部分中提到的,这主要是依赖于底层C库的模块的问题。你必须为每个平台生成不同的文件。

同样,目前还没有让你分发这些文件的构建系统,所以你必须依赖AWS、DO、CDNs或其他应用商店,如JFrog的Artifactory或Sonatype的Nexus。

更多详情:https://github.com/linkedin/shiv

Pipx

虽然不是构建应用程序或分发它们的方法,但Pipx提供了一种不同的方式来安装它们。它与你的操作系统一起工作,以隔离虚拟环境及其依赖项,更接近于Homebrew等系统对OSX的作用。

Pipx提供了一种简单的方法,可以让你将包安装到隔离的环境中,并全局地公开它们的命令行入口点。它还提供了一种机制来列出、升级和卸载这些包,而不涉及虚拟环境的细节。

一个很好的例子就是linter的使用。假设你在多个python应用程序上工作,每个应用程序都有一个单独的virtualenv,你希望使用flake8在所有应用程序上执行相同的linting操作。

代替将flake8模块安装到每个virtualenv中,你可以使用Pipx来安装一个全系统范围的flake8命令,该命令在每个环境中都可用,但运行在它们自己完全独立的环境中。

更多详情:https://pypi.org/project/pipx/

单文件可执行文件

有时,你希望为客户提供一个不需要预装库即可运行的可执行文件,就像你使用Docker或Pex一样。

这里描述的机制可以帮助你完成此任务。和前面的类别一样,它们都需要某种形式的对象或应用商店来帮助分发。

PyInstaller

虽然我们已经讨论了PyInstaller,但是在这个类别中还是值得再次提及它,因为这是它的主要功能之一。

它可以生成整个应用程序的单个可执行文件,并绑定所有依赖项。你可以为每个操作系统创建一个,它就可以像任何其他本机应用程序一样运行。

PyOxidizer

作为打包和分发领域的最新产品之一,PyOxidizer非常有前途。它利用了为Rust编程语言创建的打包工具。

与PyInstaller非常相似,你可以完全控制想要绑定到其中的所有内容,但它也可以允许你执行类似Pex或Shiv的代码。这意味着你可以创建你的包,使它作为一个REPL运行,其中的所有依赖项都已预先安装。

分发一个包括REPL的完整Python环境会产生一些令人兴奋的应用程序,特别是对于需要多个包来进行数据探索的研究团队或科学计算。

与PyInstaller相比的一个优点是,它不是提取到文件系统,而是将自身提取到内存中,从而大大缩短了实际的Python应用程序的启动时间。

这个特性与PyInstaller有类似的缺点。你必须将任何内部引用调整为__file__或类似的操作,因此它们依赖于运行时PyOxidizer配置的环境。

更多的细节可以在他们的官方文档中找到,但我们也在这篇文章中对此做了很多的介绍。

Nuitka

除了使用一个绑定的解释器执行Python代码之外,你还可以选择将代码编译为C。这带来了几个好处,包括更快执行的可能性,因为C编译器可以执行解释器无法执行的优化。

Nuitka是为将Python代码编译成C而构建的系统。虽然这个概念类似于更广为人知的Cython,但它不是一种单独的语言。它还能做Cython做不到的事情,比如抓取依赖项并将所有东西编译成一个二进制文件。

生成的可执行文件能在本地代码中以更快的速度运行,并且不需要提取。

编译可能会变得很复杂,尤其是考虑到平台的复杂性时。但是如果你为它安排好了时间,你就能获得好处。我以前成功地做过几次。

更多详情:https://nuitka.net/

应用商店体验

我们几乎每天都在使用的其他应用程序分发系统:应用商店。此软件用于安装和维护其他应用程序。

就像Apple App Store或谷歌Play Store一样,在Linux中也有类似的机制来支持简单的集成。

Snapcraft

Snapcraft提供标准的应用商店体验。你可以将你的应用程序发布到他们的商店,用户可以在那里发现并安装它。

安装是独立的,以避免与其他应用程序发生冲突,并且它可以跨Linux发行版工作,包括库依赖项。

安装后,应用商店会自动将应用程序保持在最新的稳定版本,并提供一种机制来在保留数据同时恢复到以前的状态。

Ubuntu管理着这个商店,所以你在打包了你的应用程序(或者他们所说的snap)之后,你必须用一个注册的Ubuntu One帐号将这个snap发布到商店。

更多详情:https://snapcraft.io/

Flatpak

另一个与Snapcraft非常相似的概念是Flatpak。

它还通过使用容器技术为应用程序提供隔离来提供与FlatHub.org类似的存储体验。不过,您也可以托管自己的私有hub,或者在单个文件中分发包。

Flatpak包还可以利用一些桌面集成功能。它们提供了诸如位置检测、访问应用程序外部资源的能力(很像您的手机请求权限去打开文件或URL)、通知、窗口装饰等信息。

更多创建您的第一个Flatpak的细节和说明,请查看这里:http://docs.flatpak.org/en/latest/first-build.html#

总结

我们拥有一个完整的、功能丰富的应用程序打包和分发机制生态系统。其中大多数都不是特定于Python语言的,但是很容易与它进行集成。

虽然分发应用程序看起来有很多选择,但我希望这里应用的分类能帮助您根据你可以控制的部分选择最适合您需要的方式。

英文原文:https://tryexceptpass.org/article/distributing-python-applications/ 
译者:Nothing

本地分发_2020年分发Python应用程序的12个热门途径相关推荐

  1. 更适合python的应用程序_一些很棒的Python应用程序

    我们可以从180多个成功发布的Python软件案例中学到什么. 我很高兴地发布一些很棒的Python应用程序,这是一个手工整理的180多个项目的列表,所有这些都是: 1.带有在线源代码仓库的免费软件. ...

  2. python开发应用程序错误怎么办_编程中遇到的Python错误和解决方法汇总整理

    开个贴,用于记录平时经常碰到的Python的错误同时对导致错误的原因进行分析,并持续更新,方便以后查询,学习. 知识在于积累嘛!微笑 +++++++++++++++++++++++++++++++++ ...

  3. python程序_正确配置Python应用程序

    让我们来讨论一下如何配置Python应用程序,特别是那些可能存在于多个环境中的应用程序--开发环境.模拟环境.生产环境等等-- 应用程序中使用的工具和框架并不是特别重要,因为我将在下面概述的方法是基于 ...

  4. python爬取换页_一个可识别翻页的简易Python爬虫程序

    同学拿出一个需求:从某课程教学网站上爬取所有课程的主页面,以及课程简介栏目内容. 于是在之前做的那个练手级的Python爬虫程序中进行修改,最终实现了该功能.与之前那个爬虫不同,这里每一个大类的课程下 ...

  5. 编写python程序、计算账户余额_小明有20w存款存在余额宝中,按余额宝年收益为3.35%计算,用Python编写程序计算,多少年后小明的存款达到30w?...

    [判断题]卤素灯泡是在灯泡内充入氟.氯等卤素气体. [单选题]我国刑法第12条关于溯及力的规定采取的是( ). [填空题]本地局域网 LAN 内, () 和无绳电话速率较低,主流带宽是 100kbps ...

  6. 怎么抓python程序的包_如何在AWS上部署python应用程序

    如何在AWS上部署python应用程序,学姐呕心沥血亲自总结,亲测有效,比网上看网上大把大把的文档要快得多! 作者:蕾学姐 亚马逊云计算服务(Amazon Web Services,缩写为AWS),由 ...

  7. azure web应用部署_使用Visual Studio Code将Python应用程序部署到Azure Functions

    azure web应用部署 In this article, we are going to build a small python application and deploy it to Azu ...

  8. 一个简单的python爬虫程序

    #简介 在每次论文被拒再投的过程中,都需要查询最近的与自己论文相关的会议列表.每到这种情况,我一遍采用的是遍历会伴www.myhuiban.com的网站,然后逐个查看会议,关注的有三点,投稿日期,cc ...

  9. 有趣的python小程序(附效果和程序)

    目录 1.生成漂亮的樱花树 2.绝美的静态樱花树 3.魔法少女小圆动漫形象 4.利用python播放本地mp3音乐 5.利用python弹奏天空之城 6.手绘风格的图表模块 7. 雨落在地面的动态图 ...

最新文章

  1. cxgrid列高度行宽度定义
  2. Bootstrap4+MySQL前后端综合实训-Day09-PM【实训汇报、在同一校园网下,查看别人的项目——ipconfig】
  3. boost::type_index模块实现一个类型中获得简短的和人类可读的类型名称
  4. 鼠标放到控件上 DIV悬浮提示效果(四种)
  5. SQL Server 2008中的代码安全(四):主密钥
  6. HDU6223 - Infinite Fraction Path
  7. 正则表达式 - 去掉乱码字符/提取字符串中的中文字符/提取字符串中的大小写字母 - Python代码
  8. linux shell切割脚本,自动分割日志bash shell脚本
  9. C# Json 和对象的相互转换
  10. 李运华《从零开始学架构》——架构设计三原则
  11. tp6中kafka使用
  12. 计算机基础操作知识带答案,计算机应用基础知识试题带答案
  13. CNCERT:2012年中国互联网网络安全态势综述
  14. I-SVM SVM增量学习
  15. Python获取 当前目录、上一级目录
  16. 基于FPGA交织的实现
  17. 福州大学计算机学院奖学金,2018年福州大学硕士研究生奖学金和助学金政策
  18. mysql:SQL语言包含4个部分
  19. Unity-托管代码剥离(link.xml使用)
  20. python驱动photoshop_将photoshop纳入基于python的pipeline接口系统

热门文章

  1. 发票抬头是什么意思?
  2. 关于AutoResetEvent 和ManualResetEvent
  3. 3、PV、UIP、UV指的是什么
  4. 中小企业邮件系统选型攻略
  5. 云服务器上MySQL安装教程(Windows)
  6. C语言编写工资管理系统类似学生管理系统
  7. extjs获取元素name属性值_【ExtJS】各种获取元素组件方法
  8. ios 获取最后一个cell_关于ios:向UICollectionView的第一个和最后一个单元格添加填充...
  9. c语言中fr,关于frwite()函数的一个问题,弄了好久就是不行,求解啊!
  10. 会做饭的机器人曰记_CCTV.com