Python开发者面向文档编程的正确姿势

概述

目前成都创新互联公司已为成百上千的企业提供了网站建设、域名、网络空间、成都网站托管、企业网站设计、姚安网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。

秦人不暇自哀,而后人哀之;后人哀之而不鉴之,亦使后人而复哀后人也! –论面向文档编程的重要性

如果想看见识一个人写代码的功力,注释其实是区分老司机和小鲜肉的一个显著的分界线(有没有观察到你们公司的领导基本都在开会或者写文档),通常情况下老司机的文档量与代码量是1:1的比例,而新人往往认为写完功能模块就已经可以完成任务了。生产环境中需要面对现实中大量复杂的业务逻辑和数据校验并与各方对接,文档质量和代码质量就被提升到了相同的高度。很多人没有写注释的习惯,大多数不是因为懒惰,一方面是没有意识到写文档的好处,另一方面是不了解这方面的工具。毕竟从管理上依赖于人的主动性是远不如依赖于工具有效的。本文介绍如何利用Python注释提升文档书写的质量以及效率的小技巧。

Python

在实际生产中,机器学习工作现在看起来,白天像是个算法工程师的活,晚上就变成运维+测试了。Python 一直以来也都受到测试工程师和运维工程师的偏爱,下面是几个经典的注释活用case。

用注释写单元测试:doctest

单元测试是代码开发环节必不可少的一环,对于Bug定位和代码质量而言是非常重要的。现在最广为人知的单元测试框架就是Unittest,它借鉴了Java中成熟的单元测试框架的JUnit。即使像Django还对这个框架有特殊的支持,然而在实现Unittest的时候会感觉确实比较啰嗦,setup,teardown…在维护单元测试的时候很多时候感觉力不从心。

一个巧妙的方式可以是通过doctest,用docstring注释的方式来完成单元测试,由于每个方法def下面都先跟着一段测试用例,然后紧跟着就是代码正文,这样一来很方便我们测试现有代码的质量,另一方面又便于修改。

举个例子:

 
 
 
 
  1. def factorial(n):
  2.     """Return the factorial of n, an exact integer >= 0.
  3.  
  4.     >>> [factorial(n) for n in range(6)]
  5.     [1, 1, 2, 6, 24, 120]
  6.     >>> factorial(30)
  7.     265252859812191058636308480000000
  8.     >>> factorial(-1)
  9.     Traceback (most recent call last):
  10.         ...
  11.     ValueError: n must be >= 0
  12.  
  13.     Factorials of floats are OK, but the float must be an exact integer:
  14.     >>> factorial(30.1)
  15.     Traceback (most recent call last):
  16.         ...
  17.     ValueError: n must be exact integer
  18.     >>> factorial(30.0)
  19.     265252859812191058636308480000000
  20.  
  21.     It must also not be ridiculously large:
  22.     >>> factorial(1e100)
  23.     Traceback (most recent call last):
  24.         ...
  25.     OverflowError: n too large
  26.     """
  27.  
  28.     import math
  29.     if not n >= 0:
  30.         raise ValueError("n must be >= 0")
  31.     if math.floor(n) != n:
  32.         raise ValueError("n must be exact integer")
  33.     if n+1 == n:  # catch a value like 1e300
  34.         raise OverflowError("n too large")
  35.     result = 1
  36.     factor = 2
  37.     while factor <= n:
  38.         result *= factor
  39.         factor += 1
  40.     return result
  41.  
  42.  
  43. if __name__ == "__main__":
  44.     import doctest
  45.     doctest.testmod() 

上面是官网提供的一个求N的阶乘函数示例,在docstring 中通过 >>>符号来开始一个单元测试,之后换行输入预期结果即可。实际上就是复制粘贴一下调试过程和结果,真的再简单不过了,想实现TDD也因此变得非常轻松。

用注释写API文档:apidoc

在我们完成机器学习模型后,想要提供一个对外服务的接口以贡献我们的算力时就需要完备的API文档,也是通过API的调用才能为我们的模型提供源源不断的校验数据,对于提升模型效果有非常实际的意义。对大多数人而言调用API来完成开发都是一件比较开心的事情,因为我们可以少做很多工作就可以实现强大功能。然而,当我们需要对外提供API时就要面临不一样的考验了,接口鉴权、接口设计、版本控制、并发问题、日志埋点…这些都是需要面对的新问题,而利用 apidoc 可以很好地解决这些API文档中常见的诸多问题,相当于通过模板提升了我们的接口设计的能力。

apidoc为Python提供了一种类似于 docstring 的方式来写API文档,从语法上看比较类似于 R中的roxygen,都需要用户以 @xxx 符号作为一个开头,随后书写相关的定义和功能。

举个例子:

下面是一个API接口的定义方法,最核心的部分就是

  1. 路由
  2. GET/POST方法
  3. 名称/分组
  4. 参数与调用例子

(这年头没有用例的代码都是耍流氓)

 
 
 
 
  1. """
  2. @api {get} /user/:id Request User information
  3. @apiName GetUser
  4. @apiGroup User   
  5. @apiParam {Number} id Users unique ID.  
  6. @apiSuccess {String} firstname Firstname of the User.
  7. @apiSuccess {String} lastname  Lastname of the User.
  8. """ 

我们可以直接撸一个官方示例来学习如何使用apidoc。

首先,下载示例源码

 
 
 
 
  1. git clone https://github.com/apidoc/apidoc
  2. cd apidoc 

然后,安装 apidoc 组件

 
 
 
 
  1. sudo npm install apidoc -g

接着,利用官方代码来制作一个例子,并且访问即可。

 
 
 
 
  1. apidoc -i example/ -o output/ -t template/
  2. open output/index.html 

几个参数的含义如下:

-i:input,表示输入的文件夹

-o:output,表示输出文件夹

-t:template,表示模板文件,通过替换模板我们可以修改文档皮肤

在 example 文件夹下,我们需要在apidoc.json 中填写配置文件,定义文档的header和footer部分内容,其余的文件会被自动识别出其中的docstring作为API文档的一部分。

由于apidoc的官方文档非常简单清晰,所以这里不过多强调语法。

apidoc 还为我们提供了接口调试的功能,在实际使用的时候要注意:

我们需要一个web server 才可以使用这个接口调试的功能

要注意跨域的问题。

通过版本对比,我们还可以快速排查API接口的变化情况。需要注意的是这个功能要求我们要将历史的文档记录也要保存在该目录下的文件中,通常我们可以把历史的注释输出到一个特定文件中保存。

总的来说,虽然,API文档的书写并不是一件难度非常高的事情,却能体现系统模块设计和用户体验设计的功力,我们应该对那些无代码示例,无版本控制的API文档say no!

用注释写命令行接口:docopt

利用docopt,我们可以在注释中直接声明文件的命令行传入参数,而不需要通过 argvs变量来捕获输入值再做判断,这在调用运维脚本或者若干任务调度脚本的时候尤其管用,极大地提升了CLI的效率。

举个例子:(此处代码仅供参考)

 
 
 
 
  1. """Usage:
  2.   fiannceR.py tcp   [--timeout=]
  3.   fiannceR.py serial  [--baud=9600] [--timeout=]
  4.   fiannceR.py -h | --help | --version
  5.  
  6. """
  7. from docopt import docopt
  8.  
  9. if __name__ == '__main__':
  10.     arguments = docopt(__doc__, version='0.1.1rc')
  11.     print(arguments) 
 
 
 
 
  1. fiannceR.py tcp 0.0.0.0 3838

这里的 arguments 将传出一个字典对象,以Key-Value的形式将命令行中的输入值捕获。

 
 
 
 
  1. {'--baud': None,
  2. '--help': False,
  3. '--timeout': None,
  4. '--version': False,
  5. '-h': False,
  6. '': '0.0.0.0',
  7. '': '3838',
  8. 'serial': False,
  9. 'tcp': True} 

总结

如果真的要从数据撸到模型、接口,那么一排注释的画面真是美得不敢想象。

 
 
 
 
  1. """unitest
  2. >>> FinanceR('20161001')
  3. 21.01
  4. """
  5. def FinanceR(date):
  6.     price = get_price(date)
  7.     return(price)
  8.  
  9. class(BaseHandler):
  10.     def get(self):   
  11.         """apidoc
  12.            @api {get} /price/:date 获取当前价格
  13.            @apiName GetPrice
  14.            @apiGroup Quota
  15.  
  16.            @apiParam {Number} date 交易日期
  17.  
  18.            @apiSuccess {String} price
  19.         """
  20.         date = self.get_argument('date',None)
  21.         try:
  22.             price = FinanceR(date)
  23.             self.write({'data':{'price':price},'response':{'message':'success','code':200}})
  24.         except Exception as e:
  25.             self.write({'data':None,'response':{'message':str(e),'code':404}})
  26.             
  27. """Usage:
  28.   fiannceR.py tcp   [--timeout=]
  29.   fiannceR.py serial  [--baud=9600] [--timeout=]
  30.   fiannceR.py -h | --help | --version
  31.  
  32. """
  33. from docopt import docopt
  34.  
  35. if __name__ == '__main__':
  36.     arguments = docopt(__doc__, version='0.1.1rc')
  37.     print(arguments) 

欢迎大家留言讨论,给出更多应用案例,交流分享。

参考文献

  • APIDoc
  • Python 指南:测试你的代码
  • doctest
  • nose is nicer testing for python
  • tox: standardize testing in Python
  • Biopython测试框架
  • Docopt
  • Sphinxdocopt.R

网页标题:Python开发者面向文档编程的正确姿势
URL分享:http://www.shufengxianlan.com/qtweb/news12/65962.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联