开发环境准备
- 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,环境配置很浪费时间。
网友评论