美文网首页程序员
Python项目的开发规范

Python项目的开发规范

作者: Wayne维基 | 来源:发表于2019-12-30 12:00 被阅读0次

开发环境准备

  • python 3.x - 版本3以上
  • pyCharm - 推荐的IDE
  • pip3 - python的依赖管理工具
  • virtualenv - 虚拟环境

一个web项目的目录结构示例(flask为例)

├── README.md git的工程介绍文件
├── .gitignore git忽略配置
├── requirements.txt 工程的python依赖配置
├── app.py flask的启动文件
├── config.py 工程配置
├── common 公共方法
│ ├── init.py
│ └── logger.py
├── controller 提供视图的控制层
│ ├── init.py
│ └── user_controller.py
├── service 服务层 or 应用层,可以下面再抽象领域层
│ ├── init.py
│ └── user_service.py
├── model 数据层定义各种entity
│ ├── init.py
│ ├── user.py
├── doc 文档
│ ├── sql 建表语句
│ └── 部署.md
├── log 日志
├── static 静态文件
├── templates 前端模版也可以放到static目录下
└── venv 虚拟环境目录

开发规范

1 在虚拟环境中运行python程序

虚拟环境提供一个隔离环境,便于项目之前的依赖分割。

  • 安装 virtualenv
pip3 install virtualenv
  • 进入工程目录,创建venv文件夹
    只有首次创建环境需要输入该命令
virtualenv --no-site-packages venv

--no-site-packages 指定是一个干净的开发环境

  • 进入venv
    注意之后每次开发需要进入一次venv
source venv/bin/activate

控制台出现(venv)前缀,说明进入成功

    • image.png
  • 退出 venv
deactivate
  • 在pycharm中
    通过 preferences --> project --> interpreter --> 创建虚拟环境
    • image.png

2 利用pip3管理依赖

上一步骤进入了venv环境,首次进入是一个干净的no-site-packages的环境,利用requirements.txt导入项目的依赖

  • 利用requirements.txt导入依赖
pip3 install -r requirements.txt
  • 虚拟环境下的依赖有变化,利用freeze来更新requirements.txt
pip2 freeze >requirements.txt

3 web项目部署推荐使用nginx + gunicorn的方式

  • Flask or Django默认的httpserver是simpleHTTPServer,单线程,不适合生产环境使用,推荐使用 nginx + gunicorn部署线上环境的HTTPServer

编程建议

1 使用换行,空行和空格让代码布局更合理,更可读

  • 逗号分号之前不要有空格
  • 二元运算前后都有空格,比如 = , >, in, not in
  • 可以利用pycharm自带的code format来调整

2 数据交换不要使用中间变量

temp = x
x = y
y = temp

修改为

x,y = y,x

3 学会利用 Lazy evaluation

  • if x or y,x数值更大概率为true
  • if x and y,x更大概率为false
  • 学会使用生成器表达式 yeild

4 使用枚举来替代数字

  • eg:季节,使用枚举的spring,summer来代替程序中本来要使用的1,2

5 慎重使用type来做类型检查

if type(n) is types.IntType
type检查的类型经常不准

  • 对于用户自定义类型,不要用type
  • 实例类型,type返回结果是 instance,控制精度比较差
  • 内建类型用type检查问题不大,但是要记住type什么时候可用什么时候不可用学习成本高,所以不建议用

推荐使用:isinstance(object, classinfo)

6 除法操作前都转化为浮点数再计算

python中除法和取整是一个表达式,如果不转换为浮点数,计算结果可能是取整

3/2  # 得到1
1.0 * 3/2 # 得到1.5

7 尽量避免eval表达式,防止注释式攻击

8 list的遍历用enumerate(),字典遍历用iteritems()

alist = ["1", "2"]
for index, a in enumerate(lista):
     print(index, a)

bdict = {"1": "2"}
for k, v in bdict.iteritems():
    print(k, v)

9 区别is和==

  • is是内容和地址完全一致,用于对象比较
  • == 是值一致,用于内容比较

10 考虑兼容性,尽可能使用Unicode

str = u"sdfsf"  # 就是字符前都加上u,

python的编码问题是一个很头痛的问题,加上u可以减少很多编码问题代码的错误。

11 import使用规范

  • 优先使用 import A
  • 根据实际情况使用from A import B
  • 避免使用 from A import * ,容易造成命名空间错误

12 i+ = 1 不等于 ++i

13 用with表达式做文件读写

with表达式会自动处理资源关闭

with open("test.txt", "w") as f:
     f.write("test")

14 建议 if 后都配套写个 else

else 中如果没有逻辑,可以输出一条日志

15 python中的空值判断

注意以下情况都可能相当于其他语言中的if x == Null

  • None
  • False
  • 0,0L,0.0,0j
  • "",(),[],{}
  • len(),nonzero()

16 字符串连接用join,不是 +

str = "-";
seq = ("a", "b", "c"); # 字符串序列
str.join( seq );

17 注意可变对象的复制会共享内存

lista = [a]
listb = lista
lista此时修改也会修改listb

18 学会使用列表表达式,简化表达

In [4]: [i*2 for i in range(10)]
Out[4]: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

In [5]: [i*2 for i in range(10) if i == 4]
Out[5]: [8]

19 使用copy深拷贝对象

20 使用Counter进行计数统计

import collections
obj = collections.Counter('aabbccc')
print(obj)

#输出:Counter({'c': 3, 'a': 2, 'b': 2})

21 使用argparse处理命令行参数

import argparse
parser = argparse.ArgumentParser()
parser.parse_args()

22 使用pandas处理大型csv文件

pandas支持大文件处理

23 使用multiprocessing(多进程)克服GIL的缺陷

24 不要用大小写来区分文件,建议路径都用小写

windows 大小写【不】敏感,Filepath 和 filepath一样
linxu/mac 大小写敏感,Filepath 和 filepath不一样
所以不要用大小写来区分两个文件或者路径,避免不同系统下运行结果不一直,通常路径下都不用大写,全用小写。

25 注意python有处理精度问题

>>> 0.1 + 0.2
0.30000000000000004

26 注意init() 不是类的构造方法

python object类有两个内置方法:
def init(self, *args, **kwargs): # real signature unknown
pass

@staticmethod # known case of new
def new(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass

new() 返回的是类的对象才是构造方法
init()是对于self这个实例的属性进行赋值,
在这里理解两个内置变量真正的含义

  • self是实例
  • cls是类

一般情况不需要覆盖new(),工厂方法通常是用new()来写,初始化一般用init()来写。
初始化的init()在继承中,需要显示调用super(A, self).init()才会初始化父类方法。

25 理解变量名字查找机制

1 优先局部,函数内部,也就是locals()
2 其次,找模块内,也就是globals()
3 最后找内置模块,也就是builtin

注意:
1 如果有赋值语句,变量默认是局部
2 闭包情况下面代码报错

def fun1():
    a = 1
    
    def fun2():
        b = a + 1
        a = b + 1
    return fun2

原因是:fun2中有a = b + 1,所以在fun2中的a是局部变量,b = a + 1这一行会出现a未定义就使用的错误。
解决方式:
1 global a
2 python3中
nonlocal a

26 类属性内置方法调用顺序:getattribute()和getattr()

定义一个类A,有属性b
调用A.b的时候调用:getattribute()
调用A.c的时候,先调用getattribute(),找不到,然后调用getattr(),再找不到才最终抛出异常。

覆盖这两个方法,注意一下这个机制。

27 调用traceback.print_exc()输出完整调用栈信息

28 pickle可以用cPickle优化性能

import cPickle as pickle

注意pickle使用的局限:
1 只能在python语言中使用
2 pickle不是原子操作
3 pickle没有安全性校验,所以序列化中可能存在注入式攻击
比如:
pickle.loads("cos\nsystem\n(S'dir'\ntR.")
用户可以继承pickle.Unpickler重写find_class()来解决

注意事项

1 尽量不要用Fedora和RedHat以及CentOS中的Yum,当前Yum只支持python2.7,环境配置很浪费时间。

相关文章

  • Python项目的开发规范

    开发环境准备 python 3.x - 版本3以上 pyCharm - 推荐的IDE pip3 - python的...

  • 随心所欲在python不同版本间切换

    平时用python开发多个项目的时候,尝尝遇到python版本不一样的问题,例如A项目使用python2开发,B项...

  • 前端开发规范

    前端开发规范 规范目的 命名规范 结构化规范 注释规范 编码规范 CSS 规范 规范目的 为提高团队协作效率 便于...

  • vue开发规范

    Vue 开发规范目录及说明 规范目的 命名规范 结构化规范注 释规范 编码规范 CSS 规范 规范目的 为提高团队...

  • 圆方圆python入门:如何学习(二)

    python如何学习(二) 一、编程开发规范 作为一门开发语言,python自然也有自己的编程规范,以下是特有且必...

  • iOS开发规范

    iOS开发规范 目录 编写目的 制定开发规范,可以在团队内部形成统一的开发习惯,减少协作的理解成本。此开发规范主要...

  • 如何使用Pycharm新建一个项目

    Pycharm已经是一款非常流行的集成开发环境,是写Python项目的最好的集成开发环境,使用Pycharm编写项...

  • Python开发规范

    Python风格规范 本项目包含了部分Google风格规范和PEP8规范,仅用作内部培训学习 命名规范 Pytho...

  • Web前端开发规范文档

    Web前端开发规范文档 规范目的: 使开发流程更加规范化。 通用规范: TAB键用两个空格代替(WINDOWS下T...

  • Web前端开发规范文档

    Web前端开发规范文档 规范目的: 使开发流程更加规范化。 通用规范: TAB键用两个空格代替(WINDOWS下T...

网友评论

    本文标题:Python项目的开发规范

    本文链接:https://www.haomeiwen.com/subject/zrhjnctx.html