Python 编程规范系列大纲

  1. Python 代码规范
    1. flake8 代码检查工具
    2. wemake python style
  2. Python poetry 包管理
  3. Python 工具配置
    1. commitizen
    2. isort
    3. black
    4. pylint
    5. falkehell
    6. pre-commit
    7. tox & nox 测试环境管理
  4. Python mkdocs 文档构建
  5. Python pytest 单元测试
  6. Python cookiecutter 项目模板生成工具
  7. Python Github 开源项目维护流程
    1. Github Action
    2. pull request
    3. git rebase 说明

前言

  过去在项目组开发,需要快速迭代,通常都是面向美术编程,这个需要快准狠地解决问题,至于代码怎么写其实是没有任何要求的。
  但是这对于长线维护来说简直是灾难,当这种代码越来越多之后,就会变成一堆没人敢碰的屎山代码。
  那怎么才能写出可以长期维护的代码呢?
  下面我会开一个 Python 编程规范 系列,整理出一整套 Python 的编程规范,以及配套的工具。
  这个过程是这小半年来的一次总结,这里诚挚地感谢我的同事 龙浩 ,它教会了很多~

Python 代码规范

  1. 谷歌规范 styleguide | Style guides for Google-originated open-source projects
  2. Maya Python 开发规范: Python Scripting for Maya Artists | Chad Vernon
  3. TA 101: theodox/ta_101: a coding standards doc for technical artists (github.com)

  其中我结合自身理解,翻译了 Maya Python 开发规范TA 101,大家可以自行参阅。

文件头部统一写法

  我们的代码优先采用 Python3 写法,因此根据谷歌规范,所有的代码文件需要加上下列规范
  __future__ 模块用来兼容 Python3 写法
  coding:utf-8 兼容 utf-8 编码

1
2
3
4
5
6
7
8
# -*- coding: utf-8 -*-
"""
module docstring
"""

from __future__ import division
from __future__ import print_function
from __future__ import absolute_import

  from __future__ import division 可以引入整数相除可以得到小数 (Python2的默认环境是得到整数)
  from __future__ import print_function 可以让 print 关键字变为 Python3 的 print 方法,可以在 lambda 里面使用 print
  **from __future__ import absolute_import 引入绝对导入

  division 会导致 OpenMaya 一些类型的运算符失效

PowerPoint プレゼンテーション (square-enix.com)

  原因是引入 division 之后 除法 除法 __truediv__ 而不再是 __div__ 了

enter image description here

backport 兼容库

six - py2 & py3 兼容

Github: benjaminp/six: Python 2 and 3 compatibility library (github.com)

  six 库提供了统一的 API 解决了 Py2 Py3 不统一的问题。
  比如加入 metaclass

1
2
3
4
#Python2
import abc
class TestClass(object):
__metaclass__ = abc.ABCMeta
1
2
3
4
#Python3
import abc
class TestClass(metaclass=abc.ABCMeta):
pass
1
2
3
4
5
# py2 & py3 兼容
import abc
import six
class TestClass(six.with_metaclass(abc.ABCMeta, object)):
pass

future 模块

Quick-start guide — Python-Future documentation

1
2
3
from future.standard_library import install_aliases
install_aliases()
import queue

  可以支持大部分名字迁移的库,比如 Python2 里面用 Queue 在 Python3 下用 queue
  使用 future 库就可以用 Python3 写法在 Python2 下运行。

Qt.py Qt库兼容

Github : mottosso/Qt.py: Minimal Python 2 & 3 shim around all Qt bindings - PySide, PySide2, PyQt4 and PyQt5. (github.com)

Qt.py 的作者是 流程TD 因此影视行业多采用这个,Qt.py 是运行时 Resolve Qt 的库,因此不太兼容 pyinstaller 打包之类依赖静态分析的库,要解决这个问题可以用 qtpy 库 (qtpy 是多文件 Qt.py 是单文件)


Qt 的 Python Binding 因为一些历史瓜葛,导致拆分出了两个可用的库
PyQt & PySide
PyQt 商用付费,PySide 商用免费

两者都是 Qt C++ 封装暴露到 Python 库,使用上大部分的代码都是能够兼容的。
需要注意的部分差异有信号槽区别

1
2
3
4
5
from PyQt5 import QtCore
signal = QtCore.pyqtSignal()

from PySide2 import QtCore
signal = QtCore.Signal()


enter image description here

Maya C++ Qt 版本 PyQt PySide
2014+ 信息源 Qt4 PyQt4 PySide
2017+ 信息源 Qt5 PyQt5 PySide2
未支持 Qt6 PyQt6 PySide6

Dealing with Maya 2017 and PySide2 · Fredrik Averpil

需要注意 PySide 升级到 PySide2 的 API 由以前的两个模块拆分成了三个 (QtCore QtWidgets QtGui)
官方推荐下列的代码解决问题 信息源

1
2
3
4
5
6
7
8
9
10
11
try:
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
from PySide2 import __version__
from shiboken2 import wrapInstance
except ImportError:
from PySide.QtCore import *
from PySide.QtGui import *
from PySide import __version__
from shiboken import wrapInstance

但是上面的代码需要 * 导入,并不符合我们的代码规范
使用 Qt.py 就可以轻松解决问题

1
2
3
4
from Qt import QtCore
from Qt import QtGui
from Qt import QtWidgets
from Qt.QtCompat import wrapInstance

老版本的 Maya 使用 PySide 也会被映射到 PySide2 的调用规范上。

black 代码格式化

VScode 配置 black 工具
enter image description here
使用的 Python 必须 pip install black

Pylint 代码提示

VScode 配置 Pylint 工具
enter image description here

该选项默认是启用的
只要启用 Python 安装过 Pylint (pip install pylint)

docstring 规范

docstring有四种通用的标注规范

  • Epytext
  • reST
  • Google
  • Numpy

四种规范的样式

sphinx.ext.napoleon 支持将 Google 和 Numpy 转换成 reST

建议做到所有的函数都进行 docstirng 注释

VScode 自动生成 docstring

enter image description here
Python Docstring Generator - Visual Studio Marketplace
安装 VScode 插件

enter image description here
设定可以修改 Docstring 的生成格式。
默认生成快捷键为 ctrl+shift+2

代码 review

仓库设置必须经过 review 才能合并
review 代码可以大家共同成长,统一代码规范。

tox

THM中的tox命令行大全 - 腾讯iWiki (woa.com)

龙浩提供的 thm 仓库会提供 open-dev-shell.cmd 脚本,需要本机安装 thm
启动可以进入 thm 的命令行开发环境,配备了多个中心化部署的工具

enter image description here

利用上面的 tox -a 可以查看龙浩提供的 tox 配置命令。
使用 tox -e pkg-py 可以初始化当前仓库,生成 package.py 和 setup.py 等一系列配置文件。
可以使用 tox -e ide-code 使用中心化的 vscode 打开当前仓库

enter image description here

默认 package.py 已经配置好 docs 和 单元测试 等诸多环境。
环境变量利用 rez 的规则添加到 commands 函数里面。


日常上传代码前使用 tox -e preflight
会运行 pre-commit,blackisort 标准化所有的代码,也能提前发现一些文件错误。

后续使用 git add <文件> 命令将要提交的文件添加到 git 记录里。
commit 步骤 tox -e commit添加提交信息。(这样提交信息有统一规范)

enter image description here
参考链接


发布前可以使用 tox -e build-test <版本号> 测试是否可以正常发布 thm packages
如果 build-test 通过可以使用 tox -e build <版本号> 来发布到 thm 中心化云端上

单元测试

Unit Testing in Maya | Chad Vernon
Unit Testing in Maya (Part 2) | Chad Vernon

可以使用 龙浩 配置好的 tox 进行单元测试

Qt 单元测试

pytest-qt — pytest-qt documentation

sphinx 文档生成

使用 Sphinx 撰写技术文档并生成 PDF 总结 - 简书 (jianshu.com)

使用 Markdown 编写 Sphinx 文档

使用 龙浩 的 _build_docs 命令可以自动生成文档。

Poetry 依赖管理

Poetry | PYTHON 打包和依赖管理变得简单 (qq.com)
基于 龙浩 提供的 thm(rez) 流程,不是十分需要 poetry。

Sentry 错误追踪

Sentry | 应用程序监控和错误跟踪 (qq.com)

typing 静态类型检测

python/mypy: Optional static typing for Python 3 and 2 (PEP 484) (github.com)