Python项目脚手架

为什么需要弄脚手架?

平时,主要是开发一些工具给自己或部门使用,因此对代码管理比较随意,也不需要其他人查看或修改代码。近期,有个工具要推广给其他人使用,为了方便他们修改代码,要增加注释之类的工作。在这个过程中,发现了一大段问题,比如地址的引用,存在较多相对地址,容易发生错误,代码命名不规范等一大堆规范性问题。

为了改善自己的编码习惯、减少规范性问题,花了一些时间查找、研究Python项目管理的方式,经过几次折腾后,总算确定了自己的项目管理方式(短期内应该不会再调整了)。

环境管理

我原先使用的是Anaconda,但是后面觉得有点臃肿,适合做数据分析或机器学习,但不太适合做开发,因此改用 pipenv 进行环境管理(机器学习开发环境也是用pipenv)。

创建虚拟环境

pipenv install --python version

上述命令会生成Pipfile和Pipfile.lock,且会使用pipenv创建虚拟环境,自动生成一个随机的虚拟环境目录名。般虚拟环境目录名的前缀是你创建环境时所在的项目目录名,如在myblog目录下执行命令,虚拟环境的目录名称就是myblog-Gtn4e1q9,后半部分为随机字符串。

在windows系统下执行命令,虚拟环境的文件 C:\Users\用户名.virtualenvs 文件夹下。若要修改存储地址,则要在系统新建【WORKON_HOME】的环境变量。

pipenv --venv  # 获取当前虚拟环境的位置
pipenv --where # 寻找当前项目的根目录

激活虚拟环境

创建环境后会自动进入到虚拟环境中,当退出虚拟环境重新进入到虚拟环境则需要激活虚拟环境。

在项目目录下,执行如下命令,即可激活虚拟环境.

pipenv shell

激活虚拟环境后,所有的操作仅影响当前的虚拟环境。

包管理

安装依赖包到虚拟环境

建议使用pipenv来安装/卸载相关包,便于开发依赖包的管理。安装与卸载同理,不额外说明。

pipenv install module_name # 安装生产环境的依赖包 
pipenv install module_name --dev # 安装开发环境的依赖包

不管是否激活虚拟环境,都可以执行pipenv install module_name来安装。

若要使用pip进行安装,则按如下命令执行:

pipenv run pip install module_name

使用pipenv安装时,可能会出现lock fail。这个让我苦恼了很久,解决方案如下:

  1. 跳过lock环节,先把包安装上。
pipenv install requests --skip-lock
  1. 查看安装包的版本号,并添加到pipfile中。
pipenv graph

3.更新pipfile.lock,重新安装虚拟环节时,依赖这个文件,不能漏了。

pipenv lock --dev

导出/安装包文件

导出依赖包

pipenv lock -r > requirements_dev.txt # 不包含开发环境的依赖包
pipenv lock -r --dev > requirements_dev.txt # 包含开发环境的依赖包

也可以使用pip进行导出,不过无法区分开发环境的依赖包。

pipenv run pip freeze > requirements.txt

根据pipfile安装依赖包

pipenv install  # 不包含开发环境的依赖包
pipenv install --dev # 包含开发环境的依赖包

根据requirements安装。

pipenv install -r > requirements.txt

开发环境配置

开发环境配置,主要关注几点:代码风格统一、静态类型检查、单元测试。

使用black进行格式化我们的代码。--dev用来区分开发环境,不要忘了。

pipenv install black --dev # 安装
pipenv run black file_name/dir_name # 运行

使用isort对import进行管理。

pipenv install isort --dev # 安装
pipenv run isort file_name/dir_name # 运行

使用 flake8 保证代码风格,可以参考谷歌Python风格指南

pipenv install flake8 --dev # 安装
pipenv run flake8 file_name/dir_name # 运行

使用 mypy 进行静态类型检查。不过,Python的类型注释还是不好用。

pipenv install mypy --dev # 安装
pipenv run mypy file_name/dir_name # 运行

用 pytest 进行测试,我用的比较少,实在是懒得写测试代码。

pipenv install pytest --dev # 安装
pipenv run pytest # 运行

以上就是主要的开发环境内容,但是每次手动执行还是比较麻烦的。因此,需要用到 Git 的 pre-commit,在提交代码前自动执行相关命令。这里需要用到 pre-commit 库。

pipenv install pre-commit --dev

然后新建.pre-commit-config.yaml,并添加下述配置。

repos:

 - repo: local
 hooks:

 - id: isort
 name: isort
 stages: [commit]
 language: system
 entry: pipenv run isort {{cookiecutter.project_slug}}
 types: [python]

 - id: black
 name: black
 stages: [commit]
 language: system
 entry: pipenv run black {{cookiecutter.project_slug}}
 types: [python]

 - id: flake8
 name: flake8
 stages: [commit]
 language: system
 entry: pipenv run flake8 {{cookiecutter.project_slug}}
 types: [python]
 exclude: setup.py

 - id: mypy
 name: mypy
 stages: [commit]
 language: system
 entry: pipenv run mypy
 types: [python]
 pass_filenames: false

 - id: pytest
 name: pytest
 stages: [commit]
 language: system
 entry: pipenv run pytest
 types: [python]

最后,执行下述命令生成git hooks。

pipenv run pre-commit install

快速创建项目

开发环境的配置还是有较多内容,为了减少重复工作,需要用到 cookiecutter 进行项目创建。我已经将上述内容整合到项目模板中,执行如下命令可直接创建项目。

pip install cookiecutter # 不用安装到虚拟环境。
cookiecutter https://e.coding.net/jinuobushibili/zzz_tools/ProjectTemplate.git

除上述内容外,项目模板中还包含项目目录、项目配置等多项内容。

项目代码结构

  • docs(dir):项目文档库
  • template(dir):模板文件库
  • bin(dir):入口文件,可无
  • db(dir):数据文件地址
  • log(dir):项目日志文件
  • conf(dir):项目配置文件
  • tests(dir):测试代码
  • lib(dir):自定义的模块或包
  • sample(dir):关键代码文件,每个包单独目录
    • _ init _.py
    • main.py
    • setting.py:添加了部分目录的路径变量,如db。
  • README.md:项目说明文档
  • requirements.txt:项目依赖的三方库
  • setup.py:安装、部署、打包代码

修改项目模板

若要基于自己的需求,对项目模板进行修改的话,也是比较简单的。

变量修改

cookiecutter变量,通过 cookiecutter.json 进行修改。其中的值为默认值,在创建项目时,会要求再次确认。而变量的使用,只需在对应的文件中,使用 {{ 变量名 }}即可。但需保证文件的编码为utf-8。

目录/文件调整

cookiecutter生成的文件目录是{{cookiecutter.project_slug}},需要项目自动生成的文件要放到这个目录下。

在{{cookiecutter.project_slug}}目录下操作即可,对根目录下其他目录的修改是不会影响创建项目的。

开发环境调整

调整完以后,记得更新requirem或pipfile即可。相关操作,请查看上方对应内容。

Hooks

cookiecutter的hooks全部在hooks目录下。

  • pre_gen_project.py:项目创建前
  • post_gen_project.py:项目创建后

结合cookiecutter变量与hooks,可以进行许多复杂的操作。我还没怎么用。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,585评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,283评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,760评论 0 324
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,461评论 1 266
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,280评论 4 357
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,268评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,656评论 3 385
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,322评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,629评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,691评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,445评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,299评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,694评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,982评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,244评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,642评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,829评论 2 335

推荐阅读更多精彩内容