软件开发目录设计

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

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

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

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. z-index只能用在定位元素上

    弄了很久才突然想到z-index只能用在被定位的元素上. 定位的时候要注意给父级定位 在ie7里有问题的部分

  2. PAT_A1037#Magic Coupon

    Source: PAT A1037 Magic Coupon (25 分) Description: The magic shop in Mars is offering some magic cou ...

  3. js的内部特性--属性

    使用方法:通过调用Object.defineProperty(对象,"对象属性",{}进行的操作}) 当对一个对象的属性的属性类型中vlue设置为一个值时,则这个对象的这个属性的值 ...

  4. 洛谷 P4178 Tree

    #include<iostream> #include<cstdlib> #include<cstdio> #include<cmath> #inclu ...

  5. Tomcat发布项目的几种方式

    如何在浏览器访问一个xml文件 拷贝这个文件到webapps/ROOT底下, 在浏览器里面访问 直接把tomcat/webapps/ROOT目录下 浏览器访问http://localhost:8080 ...

  6. android中使用MediaPlayer和SurfaceView播放视频

    package com.test.video; import java.io.IOException; import android.media.AudioManager; import androi ...

  7. svndumpfilter - 过滤一个 Subversion 仓库的转储文件 `dumpfile'。

    SYNOPSIS 总览 svndumpfilter command [options & args] OVERVIEW 概述 Subversion 是一个版本控制系统,允许保存旧版本的文件和目 ...

  8. Oracle 五笔码函数

    五笔码 select comm.fun_spellcode_wb('数据库') from dual 结果:ORY 函数 CREATE OR REPLACE FUNCTION COMM.FUN_SPEL ...

  9. 一、基础项目构建,引入web模块,完成一个简单的RESTful API

    一.Spring Boot的主要优点: 为所有Spring开发者更快的入门 开箱即用,提供各种默认配置来简化项目配置 内嵌式容器简化Web项目 没有冗余代码生成和XML配置的要求 二.使用maven构 ...

  10. 新手创建多module mvn工程

    1.创建工程 创建一个mvn工程有两种方式,一种是通过命令创建,一种是通过idea去一步一步配置. 1.1 命令模式 mvn archetype:generate -DgroupId={groupId ...