python生成api文档_API文档自动生成工具apiDoc简介

随着移动客户端的流行,后端系统需开放越来越多的API来供客户端使用。API文档的编写和管理是一个挑战,随着API不断变化,文档必须及时更新,但编写文档也是个不小的负担。一个比较好的做法(Best Practice),就是将文档放在代码里,开发人员编写代码时同时修改文档。然后通过工具从代码中抽出文档,并生成方便用户阅读的格式。此类工具早已存在,比如Java中的javadoc。这里我们要介绍一个非常轻量级的,适用于几乎所有流行语言的,针对Restful API的文档自动生成工具-apiDoc。

工具安装

和所有的技术介绍一样,我们先从安装开始。apiDoc基于NodeJS实现,所以你需先有NodeJS及NPM环境。然后通过:

$ npm install apidoc -g

全局安装apiDoc。之后,你就可以执行下面的命令来生成文档:

$ apidoc -i src -o dest

该命令从当前工作目录的”src”子目录下读取所有代码文件,并从中抽取apiDoc的文档注释,然后生成HTML格式的文档,并保存在”dest”子目录下。执行完后,用户就可以打开”dest”下的”index.html”来阅读文档。

“apidoc”命令支持许多参数,常用的有:

-t template

根据”template”子目录下的模板生成文档,缺省时采用apiDoc的默认模板。用户也可以编写自己的模板。关于模板的细节,本文不多介绍了。

-f ".*\\.py$"

只解析Python代码。-f后的参数按正则匹配,可以设置多个-f参数。

-h

显示该命令帮助信息。

配置文件

运行apidoc前,你需先有一个配置文件,放在代码根目录下(如上例中的src目录),取名为”apidoc.json”。下面是一个标准配置文件的例子:

{

"name": "User API Document",

"version": "0.1.0",

"description": "A sample of User API document generated from apiDoc",

"title": "User API",

"url" : "http://localhost:5000",

"sampleUrl": "http://localhost:5000",

"header": {

"title": "Overview",

"filename": "header.md"

},

"footer": {

"title": "Copyright",

"filename": "footer.md"

},

"template": {

"withCompare": true,

"withGenerator": true

}

}

简单介绍下:

name, version, description

这三个配置项的内容会显示在生成文档的最上方,其中name即整个文档的大标题。

title

网页的标题,显示在浏览器标签上。

url

文档中每个API地址的前缀。

sampleUrl

当有此项时,每个API文档的最后会有Sample Request测试部分。该配置项是测试API地址的前缀。

header, footer

页面的头和尾。当多个页面都有相同的头和尾时,这个配置项就非常有用。子配置项中

title

页面左边菜单栏中显示的标题。

filename

指向页头或页尾的模板文件,apiDoc使用的是Markdown文件。

template

withCompare

生成的文档有版本比较功能。后面会介绍。默认为”true”。

withGenerator

生成的文档页尾带有一段文字,表示这个文档是由apiDoc生成的,加上这个代表对作者的尊重吧。默认为”true”。

让我们简单写下页头和页尾的Markdown文件,并将它们同”apidoc.json”放在一起,即”src”目录下。

header.md

## Overview

Below is the API doc of User APIs.

footer.md

Copyright © 2014 - 2015 [www.bjhee.com](http://www.bjhee.com/) All Rights Reserved

API文档注释

接下来,我们就要介绍最主要的部分了,就是API代码上的文档注释。这个注释一般会加在对外开放的API函数上方。这里,我们要用到本博客文章Flask扩展系列(一)–Restful中的例子。这个例子是Python代码写的,其提供了user对象的增删改查API。Python的注释是由三个双引号"""来包括,如果是Java, JS或PHP,则用/** */来包括。我们就拿单个user的GET方法来举例子:

class User(Resource):

"""

@api {get} /users/:user_id Request User Information

@apiVersion 0.1.0

@apiName GetUser

@apiGroup User

@apiPermission admin

@apiDescription API to get the user information.

@apiExample Example usage:

curl -i http://localhost:5000/users/2

@apiParam {Number} user_id The user's unique ID.

@apiSuccess {String} name Name of the User.

@apiSuccessExample {json} Success-Response:

HTTP/1.1 200 OK

{

"name": "Tom"

}

@apiError UserNotFound The user_id of the User was not found.

@apiErrorExample {json} Error-Response:

HTTP/1.1 404 Not Found

{

"error": "UserNotFound",

"message": "User {user_id} doesn't exist"

}

@apiSampleRequest http://localhost:5000/users/:user_id

"""

def get(self, user_id):

abort_if_not_exist(user_id)

return USER_LIST[user_id]

可以看到,文档注释主要是由一系列以@符号开头的参数组成,让我们来逐一介绍:

@api {get} /users/:user_id Request User Information

最主要的参数,{get}定义了HTTP请求是GET,API地址是/users/:user_id,文档中API的名称是Request User Information。

@apiVersion 0.1.0

API的版本号,默认显示在API名称的右方。该参数可用来在不同的版本之间做比较,后面会介绍。

@apiName GetUser

API名称,不影响文档。

@apiGroup User

API分组名,文档内容中和菜单栏中同一组的API会在一同显示,方便阅读。

@apiPermission admin

API的访问权限,文档中默认会API地址下面显示。没有权限要求的话,此项可以省略。

@apiDescription API to get the user information.

API的详细描述,默认显示在API名称的下方。

@apiExample Example usage:

API调用示例,该参数的下一行就是示例的内容,直到有空行结束。可以定义多个@apiExample,默认在文档中会以标签形式列出,标签名就是”Example usage:“。

@apiParam {Number} user_id The user’s unique ID.

API参数字段介绍,”{Number}“定义了字段类型,”user_id”是字段名称,后面则是字段描述。可以定义多个@apiParam字段。

@apiSuccess {String} name Name of the User.

API成功后返回的字段,如同@apiParam,”{String}“定义了字段类型,”name”是返回字段名称,后面则是字段描述。可以定义多个@apiSuccess字段。

@apiSuccessExample {json} Success-Response:

显示一个API成功返回后Response响应的示例,”{json}“代表响应体是JSON类型。该参数的下行就是响应体内容,直到有空行结束。可以定义多个@apiSuccessExample,默认在文档中会以标签形式列出,标签名就是”Success-Response:“。

@apiError UserNotFound User was not found.

API发生错误后的返回,”UserNotFound”是错误名称,后面则是错误描述。可以定义多个错误返回。

@apiErrorExample {json} Error-Response:

显示一个API错误返回后Response响应的示例,”{json}“代表响应体是JSON类型。该参数的下行就是响应体内容,直到有空行结束。可以定义多个@apiErrorExample,默认在文档中会以标签形式列出,标签名就是”Error-Response:“。

@apiSampleRequest http://localhost:5000/users/:user_id

文档提供的API Sample测试的地址。其实在”apidoc.json”中配过”sampleUrl”项后,此参数即可省去,除非这个API的测试URL比较特殊,需特别指定。

好,现在让我们把这个代码放在”src”目录下,然后执行命令

$ apidoc -i src -o dest

打开”dest”目录下的”index.html”文件,看看我们的API文档,是不是很不错?要不动动手,把这个代码的其他API文档注释一起加上吧?

参数信息重用

很多时候,不同的API有着相同的文档内容,比如相同的成功响应示例,或者相同的错误返回。当API非常多时,一个变化需要改动多处的API文档,很麻烦。能不能像写C代码一样,定义一个宏,然后在API文档注释中引用这个宏呢?答案是有,在apiDoc中,这叫继承(inherit)。首先,你要在源代码注释中用@apiDefine定义这个宏。比如,下面的注释,就是把上例中UserNotFound错误及其响应示例定义在一个名叫UserNotFoundError的宏中。此后,所有需要使用这段文档的地方,就通过@apiUse UserNotFoundError引入这个宏即可。

class User(Resource):

"""

@apiDefine UserNotFoundError

@apiError UserNotFound The user_id of the User was not found.

@apiErrorExample {json} Error-Response:

HTTP/1.1 404 Not Found

{

"error": "UserNotFound",

"message": "User {user_id} doesn't exist"

}

"""

"""

@api {get} /users/:user_id Request User Information

...

@apiUse UserNotFoundError

"""

def get(self, user_id):

# Code here

"""

@api {delete} /users/:user_id Delete a User

...

@apiUse UserNotFoundError

"""

def delete(self, user_id):

# Code here

当宏定义比较多时,怎么管理呢?我们可以把宏定义挪到代码以外去。让我们在”src”根目录下建立一个文件”_apidoc.py”。然后把上面UserNotFoundError的定义移到这个文件中。

"""

@apiDefine UserNotFoundError

@apiVersion 0.1.0

@apiError UserNotFound The user_id of the User was not found.

@apiErrorExample {json} Error-Response:

HTTP/1.1 404 Not Found

{

"error": "UserNotFound",

"message": "User {user_id} does not exist"

}

"""

执行下apidoc命令,看下效果吧。是不是和上例中一样?实际项目中,建议尽可能把所有的宏定义都写在”_apidoc.py”中。还有人会问,那这个文件太大了怎么办?你可以分出多个文件,记得给一个有意义的命名即可。这个文件也不一定是python文件,你的代码是什么语言,就用什么文件,方便其与代码中的文档注释相互拷贝。细心的朋友们还会注意到,上例的宏定义中加了@apiVersion版本信息,这说明这段宏只对特定版本有效。

定义访问权限

上面我们讲到@apiPermission参数可以定义当前API的访问权限。如果文档的读者想了解更多关于这个权限的信息呢?我们可以通过@apiDefine来定义每个权限的详细信息。

"""

@apiDefine admin Admin access rights needed.

The admin represents the administration privilege of the application.

@apiVersion 0.1.0

"""

加上这段定义后,在文档出现”admin”权限名时,后面会有个“i”符号。鼠标点击后就会弹出”admin”的详细信息。这段定义一般也放在”_apidoc.py”中。

历史版本比较

这是我认为apiDoc最酷的功能,当API更新时,不用再耗费体力查找到底哪里改动了,直接在文档上比较下就知道了。当你在文档注释中定义多个版本后,生成后的文档页面中版本号是一个下拉列表。你点击其中一个历史版本,页面就会出现比较信息,通过高亮,删除线等来告诉你哪里被改动过了(用过代码比较工具的朋友们肯定很熟悉)。

api-diff.png

怎么来添加这历史版本信息呢。其实你要做的事情很简单,就是每次API文档改动时,把原来的API文档注释复制备份到”_apidoc.py”中,然后再修改。修改完后别忘了更新版本号就行。这里我们运行个例子,在”_apidoc.py”中加上一个老版本的GET方法注释:

"""

@api {get} /user/:user_id Request User Information

@apiVersion 0.0.1

@apiName GetUser

@apiGroup User

@apiPermission admin

@apiDescription Here you can describe the function.

Multilines are possible.

@apiParam {String} id The Users-ID.

@apiSuccess {String} id The Users-ID.

@apiSuccess {Date} name Fullname of the User.

@apiError UserNotFound The id of the User was not found.

"""

然后运行下,你就可以做版本比较了。@apiDefine宏定义也可以有历史版本,要注意,这个版本号是同API注释的版本号相匹配的。比如,假设我们在上例GET方法”0.0.1”版本注释中加入@apiUse UserNotFoundError,这个时候执行apidoc命令会报错。因为它找不到”0.0.1”版本的@apiDefine UserNotFoundError定义(前面的例子中我们指定的版本号是@apiVersion 0.1.0)。所以,必须要补上”0.0.1”版的@apiDefine UserNotFoundError命令才能运行成功。

apiDoc的主要功能讲完了,这些足够让你的项目拥有一个专业的文档了吧。如果你对apiDoc感兴趣想了解更多细节的话,可以访问它的官网apidocjs.com。本例中的代码可以在这里下载。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值