Python版本的选择和项目目录规范
我应该使用哪个Python版本?
Python同时支持多个版本,这已不是什么秘密。解释器的每个次要版本都获得18个月的错误修复支持和5年的安全支持。例如,2018年6月27日发布的Python 3.7将在2019年10月(15个月后)发布Python 3.8之前得到支持。在2019年12月左右,将发生Python 3.7的最后一个错误修复版本,并且每个人都应该切换到Python 3.8。
这一点很重要,因为解释器的版本将完全是软件生命周期的一部分。最重要的是,我们应该考虑Python2
与Python3
的问题。对于使用(非常)旧平台的人来说,这仍然是一个开放而没有解决的问题。
最后,一个人应该使用哪种Python版本的问题是值得一问的。
以下是一些简短的答案:
- 版本2.6及更早版本现在已经过时了,因此您根本不必担心支持它们。如果您打算支持这些旧版本,请注意,您将更难确保您的程序也支持Python 3.x. 虽然您可能仍会在某些旧系统上遇到Python 2.6; 如果是这样的话,抱歉!
- 2.7版本仍然是Python 2.x的最后一个版本。我不认为现在有一种系统不能以某种方式提供Python 3。所以除非你再次进行考古学,否则就算了。2020年之后将不再支持Python 2.7,所以你要做的最后一件事就是建立一个基于它的新软件。
- 版本3.7是撰写本文时Python 3分支的最新版本,这是您应该定位的版本。最新的操作系统至少运行3.6,因此在您定位这些操作系统的情况下,您可以确保您的应用程序也可以使用3.7。
项目布局
开始一个新项目总是一个难题。你永远不知道如何组织你的文件。但是,一旦你对那里的最佳实践有了正确的理解,它就非常简单了。
首先,您的项目结构应该是相当基础的。明智地使用包和层次结构:深层次结构可能是导航的噩梦,而平面层次结构往往变得臃肿。
然后,避免犯一些常见的错误。不要将单元测试留在包目录之外。这些测试应包含在您的软件的子包中,以便:
- 它们不会被setuptools(或其他一些包装库)自动安装为测试顶层模块。
- 它们可以安装并最终被其他软件包用于构建单元测试。
下图说明了标准文件层次结构的外观:
setup.py
是Python安装脚本及其配套设置的标准名称以及其附带程序setup.cfg
,它应包含安装脚本配置。运行时,setup.py使用Python分发实用程序安装程序包。
您还可以向用户提供有价值的信息README.rst
(或者README.txt,或者任何适合您的文件名)。最后,该docs目录应包含reStructuredText格式的包文档,该文档将由Sphinx使用。
包通常必须提供额外的数据,例如图像,shell脚本等。不幸的是,没有普遍接受的标准来存储这些文件的位置。只需将它们放在对项目最有意义的地方:根据其功能,例如,Web应用程序模板可以templates放在程序包根目录的目录中。
还经常出现以下顶级目录:
-
etc
用于示例配置文件。 -
tools
用于shell脚本或相关工具。 -
bin
对于您编写的将要安装的二进制脚本setup.py。
我经常遇到另一个设计问题。在创建文件或模块时,一些开发人员会根据他们将存储的代码类型创建它们。例如,他们会创建functions.py
或exceptions.py
文件。这是一种可怕的方法。在导航代码时,它对任何开发人员都没有帮助。代码组织没有从中受益,它迫使读者无缘无故地在文件之间跳转。在某些情况下,存在一些例外,例如库,因为它们确实为消费者公开了完整的API。但是,除此之外,在您的应用程序中执行此操作之前请三思而后行。
根据功能组织代码,而不是基于类型。
创建一个只包含__init__.py
文件的模块目录也是一个坏主意。例如,不要创建一个新的目录hooks名为一个文件hooks/__init__.py
在它放在hooks.py就足够了吧。如果创建目录,它应该包含属于该目录所代表类别的其他几个Python文件。
还要非常小心你放在__init__.py
文件中的代码:它将在第一次加载目录中包含的任何模块时被调用和执行。这可能会产生不必要的副作用。__init__.py
除非你知道你在做什么,否则这些文件大部分时间都应该是空的。
版本编号
需要标记软件版本以了解哪一个比另一个更新。随着每一段代码的发展,每个项目都需要能够组织其时间表。
组织版本号的方法有很多种,但PEP 440引入了一种版本格式,每个Python软件包,理想情况下每个应用程序都应遵循这种格式。这样,程序和包将能够快速可靠地识别它们所需的软件包版本。
PEP 440为版本编号定义以下正则表达式格式:
N[.N]+[{a|b|c|rc}N][.postN][.devN]
这允许标准编号像1.2
或1.2.3
。
但请注意:
-
1.2
相当于1.2.0
;1.3.4
等同于1.3.4.0
等等。 - 版本匹配
N[.N]+
被视为最终版本。 - 基于日期的版本
2013.06.22
被视为无效。用于检测PEP 440
格式版本号的自动化工具如果检测到大于或等于的版本号,将会(或应该)引发错误1980
。
最终组件也可以使用以下格式:
-
N[.N]+aN
(例如1.2a1
)表示alpha版本,可能不稳定且缺少功能的版本。 -
N[.N]+bN
(例如2.3.1b2
)表示测试版,可能是功能完整但仍有错误的版本。 -
N[.N]+cN
或N[.N]+rcN
(例如0.4rc1
)表示(release)候选人,可能作为最终产品发布的版本,除非出现重大错误。虽然rc
和c
后缀具有相同的含义,但如果两者都使用,则rc
发布版本被认为比c
版本更新。
这些后缀也可以使用:
-
.postN
(例如1.4.post2
)表示发布后。这些通常用于解决发布过程中的小错误(例如发行说明中的错误)。.postN
在发布修正版本时不应该使用; 相反,您应该增加次要版本号。 -
.devN
(例如2.3.4.dev3
)表示发展版本。不鼓励使用此后缀,因为人类难以解析。它表示它符合条件的版本的预发行版:例如,在任何alpha,beta,候选版本或最终版本之前2.3.4.dev3
指示版本的第三个开发版本2.3.4
。
对于大多数常见用例,此方案应该足够了。
您可能听说过语义版本控制,它提供了自己的版本编号指南。该规范与PEP 440部分重叠,但不幸的是,它们并不完全兼容。例如,Semantic Versioning对预发布版本控制的建议使用的方案
1.0.0-alpha+001
不符合PEP 440。
许多DVCS平台(例如Git和Mercurial)可以使用标识哈希生成版本号(对于Git,请参阅git describe
)。不幸的是,这个系统与PEP 440定义的方案不兼容:首先,识别哈希值是不可订购的。
- Mongodb副本集+分片集群环境部署记录
- 线上mongodb 数据库用户到期时间修改的操作记录
- 微信小程序“授权失败”场景的处理
- 动软.net代码生成器 win2008 r2下无法连接oracle,以及vs2008模板丢失的解决
- ASP.NET Web API 支持 CORS
- oracle odp.net 32位/64位版本的问题
- Redis+TwemProxy(nutcracker)集群方案部署记录
- 金融科技新常态,未来开启拼“硬实力”阶段
- Mono 3 的默认Gc是Sgen
- Linux下Redis主从复制以及SSDB主主复制环境部署记录
- 单元测试同时支持 NUnit/MSTest
- log4net快速上手
- MySQL高可用方案-PXC环境部署记录
- Redis主从复制下的工作原理梳理
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- [数据结构] 使用最小堆思想实现哈夫曼编解码
- [数据结构] 括号符的匹配
- [数据结构] 平衡二叉查找树 (AVL树)
- 写给前端的算法进阶指南,我是如何两个月零基础刷200题
- [Java] 在Java中优雅地进行文件IO操作
- [Java] 日期与时间的一些操作
- 一起来用python实现一下十大经典排序算法
- [数据结构] 稀疏矩阵的存储
- [Python] 关于 asyncio 与 aiohttp 协程并发的探索
- [数据结构]结构体练习之复数运算
- [数据结构] 队列的链式存储实现
- [数据结构] 两个有序线性表的合并
- Spring 简介,带你打开 Spring 的大门
- go test 测试用例那些事(二) mock
- [数据结构]链式存储: 多项式求和