zengbin93 / blog

17 stars 10 forks source link

实践 - Python - 项目开发 #13

Open zengbin93 opened 6 years ago

zengbin93 commented 6 years ago

以我一个新手的理解,python中一个项目开发涉及的内容主要有:1)项目结构搭建;2)自动化doc文档生成;3)命令行工具制作(视情况而定);4)打包发布,或直接部署。

zengbin93 commented 6 years ago

项目结构

一个项目对应的就是一个文件夹,这个是项目的根目录。通常一个项目的根目录下至少会有两个文件夹,分别存放项目主要功能代码和doc文档。此外,根据项目需要可以添加其他的文件和文件夹到根目录。

zengbin93 commented 6 years ago

sphinx - 自动化doc文档生成

关于doc文档的自动生成,Python标准库中提供了一个pydoc库来完成这个任务。但是,在绝大多数项目中,sphinx都是一个更好的选择。

这里有一个适用sphinx自动生成文档的案例:https://www.jianshu.com/p/d4a1347f467b

使用sphinx自动生成文档的基本步骤

step 1. 安装 - pip install Sphinx

step 2. 编写python项目,并写好docstring

step 3. 在项目doc文件夹下面执行sphinx,配置相关参数
    1) 执行sphinx-quickstart,配置参数
    2)在source/conf.py文件中导入自己的项目路径
    3)生成rst文件 
        sphinx-apidoc -o ./source ../code/
    4)执行make html,生成html文件

step 4. 配置theme
    以readthedocs为例:
    pip install sphinx_rtd_theme
    编辑我们的source/conf.py

    导入模块:
    import sphinx_rtd_theme
    将 html_theme = "alabaster"改成如下,在加上html_theme_path
    html_theme = "sphinx_rtd_theme" html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
    最后我们再执行一次:make html

注释编写案例

# 使用 `module` 标注 
        If the stream is closed, raises `WebSocketClosedError`.
        Returns a `.Future` which can be used for flow control.
# 备注版本变动
        .. versionchanged:: 5.0
           Exception raised on a closed stream changed from `.StreamClosedError`
           to `WebSocketClosedError`.
zengbin93 commented 6 years ago

制作命令行工具

python中的命令行工具其实就是一个可以从命令行接收参数的函数。打包发布的时候,在setup.py文件中增加对应的入口就可以。

对于命令行工具的制作,python标准库中有一个argparse库,此外还有一个名为click的第三方库。但是,我个人更倾向于推荐使用fire,这个是谷歌2017年开源的工具,非常好用。

fire


官方教程:https://github.com/google/python-fire/blob/master/docs/guide.md

案例:使用dict来指定命令行可以使用的对象

import fire

def hello(name):
    return 'Hello {name}!'.format(name=name)

def add(x, y):
    return x + y

def multiply(x, y):
    """乘法

    :param int x:
    :param y:
    :return:
    """
    """查看帮助时,fire会直接把docstring展现在命令行"""
    return x * y

# entry points入口,方便打包发布
def main():
    fire.Fire({
        "hi": hello,
        'add': add,
        'multiply': multiply,
    })

if __name__ == '__main__':
    # fire.Fire()       # 直接将一个py脚本编程cli
    # 也可以使用component指定哪些
    # fire.Fire(component=hello)
    # 更推荐使用dict来限制命令行访问的对象
    fire.Fire({
        "hi": hello,
        'add': add,
        'multiply': multiply,
    })

案例:分组命令

import fire

class IngestionStage(object):
    def __init__(self):
        self.name = 'IngestionStage'

    def run(self):
        return self.name + ' Ingesting! Nom nom nom...'

class DigestionStage(object):
    @staticmethod
    def run(volume=1):
        return ' '.join(['Burp!'] * volume)

    @staticmethod
    def hello(name, age):
        """say hello to some one
        params
        --------
            --name  str  person name, eg: zb
            --age   int  person age, eg: 12
        """
        print("hello ", name,
              "; age:", age)

    @staticmethod
    def status():
        return 'Satiated.'

class Pipeline(object):
    def __init__(self):
        self.ingestion = IngestionStage()
        self.digestion = DigestionStage()

    def run(self):
        # 如果两个以上分组中有相同的函数,需要在pipeline中进行组合。
        # 在cmd中实际执行时,仅会执行指定分组下的函数。
        self.ingestion.run()
        self.digestion.run()

if __name__ == '__main__':
    fire.Fire(Pipeline)
zengbin93 commented 6 years ago

打包发布到PyPi

官方教程: https://packaging.python.org/tutorials/distributing-packages/

PyPi账户相关


发布前,你需要有一个PyPi账户,注册地址:https://pypi.org/account/register/

发布成功后可以登录查看,登录地址:https://pypi.org/account/login/

如果之前注册过,但是现在忘记了密码,修改密码地址:https://pypi.org/account/request-password-reset/

编写setup.py文件


setup.py文件定义了打包过程的一系列动作,详见:https://packaging.python.org/tutorials/distributing-packages/#setup-py

常用参数如下:

如果项目中有命令行工具,在setup.py中添加:

    entry_points={
        'console_scripts': [
            "命令= 对应函数", # 如:"debug_a = debug_a.cli:debug_a"
        ]
    }

打包 - python setup.py sdist


打包之后,项目根目录下会出现一个 dist 文件夹,打包好的文件就在这个文件夹里面。

上传到PyPi - twine upload dist/*


上传之后,就可以在PyPi的账户中看到自己的项目了。此时,在pip的官方源里面就已经有了刚刚上传的包,但是国内的一些镜像源应该是还没有同步了。如果你使用的是国内镜像源,执行pip install还没法安装刚刚上传的包,可以临时切换到官方源进行安装,代码如下:

**pip install *** -i https://pypi.org/simple/**

zengbin93 commented 6 years ago

使用tqdm实现进度条功能

tqdm(读音:taqadum, تقدّم)在阿拉伯语中的意思是进展。tqdm可以在长循环中添加一个进度提示信息,用户只需要封装任意的迭代器 tqdm(iterator),是一个快速、扩展性强的进度条工具库

from tqdm import tqdm
import time

for i in tqdm(range(100), desc='test', ncols=100):
    time.sleep(0.1)