软件开发目录设计

对于提高项目可读性、可维护性的要求就很高了。”项目目录结构”其实也是属于”可读性和可维护性”的范畴,我们设计一个层次清晰的目录结构,就是为了达到以下两点:

可读性高: 不熟悉这个项目的代码的人,一眼就能看懂目录结构,知道程序启动脚本是哪个,测试目录在哪儿,配置文件在哪儿等等。从而非常快速的了解这个项目。

可维护性高: 定义好组织规则后,维护者就能很明确地知道,新增的哪个文件和代码应该放在什么目录之下。这个好处是,随着时间的推移,代码/配置的规模增加,项目结构不会混乱,仍然能够组织良好。

Foo/
|-- bin/
| |-- foo
|
|-- foo/
| |-- tests/
| | |-- __init__.py
| | |-- test_main.py
| |
| |-- __init__.py
| |-- main.py
|
|-- docs/
| |-- conf.py
| |-- abc.rst
|
|-- setup.py
|-- requirements.txt
|-- README

1、bin/: 存放项目的一些可执行文件,当然你可以起名 script/之类得也行

2、foo/: 存放项目的所有源代码。

(1)源代码中的所有模块、包都应该放在此目录。不要置于顶层目录

(2)其子目录tests/存放单元测试代码;

(3)程序的入口最好命名为main.py

3、docs/:存放一些文档

setup.py:安装、部署、打包的脚本

4、requirements.txt:存放软件依赖的外部python包列表

README:项目的说明文件。

除此之外,有一些方案给出了更加多的内容。比如LICENSE.txt,ChangeLog.txt 文件等,这些东西主要是项目开源的时候需要用到的。

关于README[自述文件]的内容

这个文件的目的是能够简要的描述项目的信息,让读者快速了解这个项目。

它需要说明一下几个事项:

1、软件的定位,软件的基本功能

2、运行代码的方法:安装环境,启动命令等

3、简要的使用说明

4、代码目录结构说明,更详细点可以说明软件的基本原理

5、常见问题说明。

关于requirements.txt[要求]和setup.py

setup.py

一般来说用setup来管理代码的打包、安装、部署问题。业界标准的写法是用python刘雪的打包工具Setuptools来管理这些事情。这种方式普遍应用于开源项目中。不过这里的核销思想不是用标准化的工具来解决这些问题,而是说,一个项目一定要有一个安装部署的工具,能快速便捷的在一台新机器上讲环境安装好,代码部署好喝将程序运行起来 。

如果手动完成 软件的 安装环境,部署代码,运行程序,经常会出现以下问题。

1、安装环境时经常忘记最近添加了一个新的python 包,结果一到线上运行,程序就出错了。

2、python包的版本依赖问题,有时候程序中使用的是一个版本的python包,但是官网的意见是最新的包了,通过手动安装可能会出错。

3、如果依赖的包很多的话,一个一个安装这些依赖是很费事

4、新手再开始写项目的时候,将程序跑起来非常麻烦,因为可能经常忘记这么安装各种依赖

setup.py可以将这些事情自动化起来,提供效率,减少出错的概率“复杂的东西自动化,能自动化的东西一定要自动化”是一个非常好的习惯

setuptools的文档比较庞大,刚接触的话,可能不好找到切入点,学习技术的方式就是看他人是怎么用得,可以参考python的一个web框架,flask是如何写得:setup.py

当然,简单点自己写个安装脚本(deploy.sh【配置,展开】)替代setup.py也是可以的

requirements.txt

这个文件存在的目的是:

1‘方便开发者维护软件的包一辆。将开发过程中新增的包添加进这个列表中,避免在Setup.py安装一辆时漏掉软件包。

2、方便读者明确项目使用了哪些python包

这个文件的格式是每一行包含一个包的依赖说明,通常是flask> = 0.10这种格式,要求是这个格式能被pip识别,这样可以简单的通过pip install -r requirements.txt 把所有python包依赖都装好了,具体格式说明:

需求文件¶
在安装软件,特别是Python软件包时,通常会安装很多库。你刚刚做了easy_install MyPackage ,你得到了十几个包。每个软件包都有自己的版本。 也许你运行该安装,它的工作原理。大!它会继续工作吗?您是否必须提供特殊选项才能找到所有内容?你必须安装一堆其他可选件吗?最重要的是,你能再次做到吗?需求文件为您提供了创建环境的方法:一组协同工作的包。 如果您曾尝试在新系统上设置应用程序,或者稍微更新一些应用程序,并且使其失败,那么pip要求就适合您。如果你没有遇到这个问题那么你最终会这样,所以pip要求也适合你 - 要求明确,可重复地安装包。 那么什么是需求文件?它们非常简单:要安装的软件包列表。您可以创建一个需求文件,而不是运行像pip install MyApp这样的东西并获取任何库。 MyApp的
框架== 0.9.4
库> = 0.2
如果将其保存在requirements.txt中,则可以pip install -r requirements.txt。无论MyApp在setup.py中列出什么,您都将获得特定版本的Framework(0.9.4)和至少0.2版本的Library。(您可能认为可以在MyApp的setup.py中列出这些特定版本 - 但如果您这样做,则必须编辑MyApp,如果您想尝试新版本的Framework,或者如果您确定该版本,则需要发布新版本的MyApp库0.3不适用于您的应用程序。)您还可以添加MyApp不严格要求的可选库和支持工具,为人们提供一组推荐的库。 您还可以包含“可编辑”包 - 从Subversion,Git,Mercurial和Bazaar签出的包。这些就像使用-e 选项来进行pip一样。他们看着像是: -e svn + http:// myrepo / svn / MyApp#egg = MyApp
您必须使用svn +(git +,hg +或bzr +)启动URL ,并且必须包含#egg = Package,因此pip知道该URL的内容。您还可以在URL中包含@rev,例如@ 275以查看修订版275。 需求文件大多是扁平的。也许MyApp需要 Framework,而Framework需要Library。我鼓励您仍然将所有这些列在一个需求文件中; Python程序的本质是 MyApp和Library之间直接存在隐式绑定。例如,Framework可能会暴露一个Library的对象,因此如果更新了Library,它可能会直接破坏MyApp。如果发生这种情况,您可以更新需求文件以强制使用早期版本的库,并且您可以执行此操作而无需重新发布MyApp。 阅读需求文件格式以了解其他功能。 冻结要求
所以你有一套可用的软件包,你希望能够在其他地方安装它们。 需求文件允许您安装确切的版本,但它不会告诉您所有确切版本是什么。 要从已知的工作环境创建新的需求文件,请使用: $ pip freeze> stable-req.txt
这将为stable-req.txt编写所有已安装库的列表,其中 包含每个库的确切版本。您可能希望在生成后编辑文件(例如,消除不必要的库),但它将为构建需求文件提供稳定的起点。 您还可以为其提供现有的需求文件,并将其用作新文件的一种模板。所以,如果你这样做: $ pip freeze -r devel-req.txt> stable-req.txt
它将按顺序保留devel-req.txt中列出的包并保留注释。 该要求的文件格式
需求文件是一种获取pip以安装特定包以构成环境的方法。本文档描述了该格式。要了解何时应使用需求文件,请参阅需求文件。 需求文件的每一行都表示要安装的内容。例如: MyPackage == 3.0
告诉pip安装3.0版本的MyPackage。 您还可以在需求文件中请求额外内容: MyPackage == 3.0 [ PDF ]
包也可以以“可编辑”的形式安装。这将源代码放入src / distname(使名称小写)并在包上运行python setup.py develop。要表示可编辑,请使用-e,如: -e svn + http://svn.myproject.org/svn/MyProject/trunk#egg=MyProject
该#蛋= MyProject的部分是很重要的,因为虽然你可以给出的SVN位置只需安装,项目名称是在其他地方有用。 您还可以为不可编辑的网址指定鸡蛋名称。这对于指向本地文件系统上的HEAD位置很有用: 文件:///路径/要/你的/ lib目录/项目#蛋= MyProject的
或相对路径: 文件:../../ LIB /项目#蛋= MyProject的
如果你需要给pip(和关联easy_install)提示有关在哪里找到包,你可以使用-f (-- find-links)选项,如: $ pip -f http://someserver.org/index-of-packages MyPackage == 3.0
然后皮普将寻找在链路http://someserver.org/index-of-packages 匹配版本3.0的MyPackage的 -链接应该像MyPackage的-3.0.tar.gz。 如果你想从带有直接链接的tarball或zip文件安装,你不需要-f选项,你只需要传递绝对URL,如: $ pip install http://someserver.org/packages/MyPackage-3.0.tar.gz
版本控制
现在pip知道以下主要版本控制系统: 颠覆
Pip支持URL方案svn,svn + svn,svn + http,svn + https,svn + ssh。您还可以对SVN URL进行特定修订,例如: -e svn + svn://svn.myproject.org/svn/MyProject#egg=MyProject
-e svn + http://svn.myproject.org/svn/MyProject/trunk@2019#egg=MyProject
这将检查修订版 2019. @ {20080101}还将查看2008-01-01的修订版。您只能使用-e svn + ...查看特定的修订版本。 Git的
Pip目前支持通过git,git + http和git + ssh进行克隆: -e git://git.myproject.org/MyProject.git#egg=MyProject
-e git + http://git.myproject.org/MyProject/#egg=MyProject
-e git + ssh://git@myproject.org/MyProject/#egg=MyProject
传递分支名称,提交哈希或标记名称也是可能的: -e git://git.myproject.org/MyProject.git@master#egg=MyProject
-e git://git.myproject.org/MyProject.git@v1.0#egg=MyProject
-e git:/ / / / / / / / / / / / / / / /
水银
支持的方案是:hg + http,hg + https, hg + static-http和hg + ssh: -e hg + http://hg.myproject.org/MyProject/#egg=MyProject
-e hg + https://hg.myproject.org/MyProject/#egg=MyProject
-e hg + ssh://hg@myproject.org/MyProject/#egg=MyProject
您还可以指定修订号,修订哈希,标记名称或本地分支名称: -e hg + http://hg.myproject.org/MyProject/@da39a3ee5e6b#egg=MyProject
-e hg + http://hg.myproject.org/MyProject/@2019#egg=MyProject
-e hg + http://hg.myproject.org/MyProject/@v1.0#egg=MyProject
-e hg + http://hg.myproject.org/MyProject/@special_feature#egg=MyProject
义卖
Pip使用bzr + http,bzr + https,bzr + ssh, bzr + sftp,bzr + ftp和bzr + lp方案支持Bazaar : -e bzr + http://bzr.myproject.org/MyProject/trunk/#egg=MyProject
-e bzr + sftp://user@myproject.org/MyProject/trunk/#egg=MyProject
-e bzr + ssh://user@myproject.org/MyProject/trunk/#egg=MyProject
-e bzr + ftp://user@myproject.org/MyProject/trunk/#egg=MyProject
-e bzr + lp:MyProject#egg = MyProject
可以像这样安装标签或修订版: -e bzr + https://bzr.myproject.org/MyProject/trunk/@2019#egg=MyProject
-e bzr + http://bzr.myproject.org/MyProject/trunk/@v1.0#egg=MyProject
递归要求
如果您愿意,还可以参考其他需求文件,例如: -r Pylons-requirements.txt
这为您提供了一种抽象出各种要求的方法。但是,对于冻结的要求,这并不是非常友好,因为Pylons-requirements.txt中的所有内容都 将显示在冻结文件中。 索引,查找链接
您还可以 在需求文件中为--index-url和--find-links选项提供值,例如: --index-url http://example.com/private-pypi/
请注意,使用--index-url会删除PyPI的使用,而使用--extra-index-url将添加其他索引。 --find-links更加临时; 而不是一个完整的“索引”,你只需要一个指向可用包的链接的HTML页面。只需将所有私有软件包放在一个目录中并使用Apache自动索引,就可以发布软件包,以便pip可以找到它们。 --find-links总是添加剂; pip看着它能找到的一切。使用它像: --find-links http://example.com/private-packages/
请注意,所有这些选项必须在他们自己的行上。

格式说明

关于配置文件的使用方法

注意,再上面的目录结构中,没有将conf.py放在源码目录下,而是放在.docs/目录下。

很多项目对配文件的使用做法是:

1、配置文件写在一个或多个python文件中,比如此处的conf.py。

2、项目中哪个模块用到这个配置文件就通过import conf 这种形式在代码中使用配置。

这种做法不是很赞成:

1、这让单元测试变得困难(因为模块内部依赖了外部配置)

2、另外一方面配置文件作为用户控制程序的接口,应当可以由用户自由一指定文件的路径。

3、程序组件可复用性太差,因为这种贯穿所有模块的代码硬编码方式,使得大部分模块都依赖conf.py这个文件。

所有,配置的使用,更好的方式是:

1、模块的配置都是可以灵活配置的,不受外部配置文件的影响。

2、程序的配置也可以灵活控制。

能够佐证这个思想的是,用过nginx和mysql的人都知道,nginx,mysql这些程序都可以自由的指定用户配置。

所以,不应当再代码中直接import conf 来配置文件。上面的目录结构中conf.py是给出的一个配置样例,不是在写死程序直接引用的配置文件,可以通过 给main.py启动参数指定配置路径的方式来让程序读取配置内容。当然,这里的conf.py你可以换个类似的名字,或者你也可以使用其他格式的内容来编写配置文件,比如settings.yaml之类。

Day 22: 软件开发目录设计规范的更多相关文章

  1. Python记录13:软件开发目录规范

    软件开发目录规范 开发一个软件,一个工程项目,一般应该具备以下的几个基本的文件夹和模块,当然,这并不是一成不变的,根据项目的不同会有一定的差异,不过作为一个入门级的新手,建议暂时按照以下的规范编写: ...

  2. Python 浅谈编程规范和软件开发目录规范的重要性

    最近参加了一个比赛,然后看到队友编程的代码,我觉得真的是觉得注释和命名规范的重要性了,因为几乎每个字符都要咨询他,用老师的话来说,这就是命名不规范的后续反应.所以此时的我意识到写一篇关于注释程序的重要 ...

  3. python 之 软件开发目录规范 、logging模块

    6.4 软件开发目录规范 软件(例如:ATM)目录应该包含: 文件名 存放 备注 bin start.py,用于起动程序   core src.py,程序核心功能代码   conf settings. ...

  4. Python模块:Re模块、附软件开发目录规范

    Re模块:(正则表达式) 正则表达式就是字符串的匹配规则 正则表达式在多数编程语言里都有相应的支持,Python里面对应的模块时re 常用的表达式规则:(都需要记住) “ . ”   #  默认匹配除 ...

  5. python模块导入-软件开发目录规范-01

    模块 模块的基本概念 模块: # 一系列功能的结合体 模块的三种来源 """ 模块的三种来源 1.python解释器内置的模块(os.sys....) 2.第三方的别人写 ...

  6. py 包和模块,软件开发目录规范

    目录 py 包和模块,软件开发目录规范 什么是包? 什么是模块? 软件开发目录规范 py 包和模块,软件开发目录规范 什么是包? 包指的是内部包__init__.py的文件夹 包的作用: 存放模块,包 ...

  7. python基础语法10 函数递归,模块,软件开发目录规范

    函数递归: 函数递归指的是重复 “直接调用或间接调用” 函数本身, 这是一种函数嵌套调用的表现形式. 直接调用: 指的是在函数内置,直接调用函数本身. 间接调用: 两个函数之间相互调用间接造成递归. ...

  8. python浅谈编程规范和软件开发目录规范的重要性

    前言 我们这些初学者,目前要做的就是遵守代码规范,这是最基本的,而且每个团队的规范可能还不一样,以后工作了,尽可能和团队保持一致,目前初学者就按照官方的要求即可 新人进入一个企业,不会接触到核心的架构 ...

  9. python基础之迭代器、装饰器、软件开发目录结构规范

    生成器 通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大 ...

随机推荐

  1. 调整WebBrowser的默认浏览器内核版本

    原文出自:https://my.oschina.net/Tsybius2014/blog/492107 注:这个是写.net控件,其实delphi是一样的.作者已经写的比较全面了,我只是做了一点修改 ...

  2. java中的三大特性

    java的三大特性是封装.继承.多态: 继承是OOD(面向对象设计)为了更好的建模,编程的时候是OOP(面向对象编程)提高代码的复用性.这里有个注意点:一个类只有一个直接的父类,但不是只有一个父类. ...

  3. [已解决]报错: Creating Server TCP listening socket 127.0.0.1:6379: bind: No error

    问题: windows下安装Redis第一次启动报错: [2368] 21 Apr 02:57:05.611 # Creating Server TCP listening socket 127.0. ...

  4. change transformation file in PI interface

    1. Jane extends the ZTMMASKU sap table 2. Jane write the program to write the new attribute to the t ...

  5. HTTP、HTTP1.0、HTTP1.1、HTTP2.0、HTTPS

      一.HTTP HTTP(超文本传输协议,HyperText Transfer Protocol)是应用层的协议,目前在互联网中应用广泛. 它被设计用于Web浏览器和Web服务器之间的通信,但它也可 ...

  6. Puppeteer自动化测试cnode.js中文社区

    如果完全不了解puppeteer的朋友可以去看看我的这篇随笔:https://www.cnblogs.com/zlforever-young/p/11569890.html 开始之前需要了解的知识:E ...

  7. Shell 变量操作

  8. 从零开始搭建系统2.8——HDFS安装及配置

    从零开始搭建系统2.8——HDFS安装及配置

  9. 一句话的Android增量更新框架(增量更新)

    转自:http://www.jianshu.com/p/a9ec8fa780e2 Android应用更新要使用完整的新版本Apk安装,增量更新则是提供一个新旧版本偏差数据的patch包供应用下载,然后 ...

  10. loj2064[HAOI2016]找相同字符

    题意:给你两个字符串,问其中各取一个子串,有多少对相同?n<=20W. 标程: #include<bits/stdc++.h> using namespace std; typede ...