博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
包管理、插件化开发
阅读量:4130 次
发布时间:2019-05-25

本文共 4163 字,大约阅读时间需要 13 分钟。

1. 包管理

1.1 为什么实用包管理

  Python的模块或者源文件直接可以复制到目标项目目录中,就可以导入使用了.但是为了更多项目调用使用,或者共享给别人,就需要打包,或发布到网络,以便供人使用。目的也是为了复用。

Pypi(Python Package Index),公共的模块存储中心,

1.2 主要工具

1.2.1 distutils

  官方库distutils, 来构建、安装包。从1998年就是标准库的一部分,直到2000年停止开发。

1.2.2 setuptools

  它是替代distutils的增强版工具集,包含easy_install工具,使用ez_setup.py文件。支持egg格式的构建和安装。提供查询、下载、安装、构建、发布、管理等包管理功能。

setuptools是包管理的核心模块。
  后来,setuptools开发缓慢了,出现基于setuptools的distribute来替代setuptools。2013年,这两个项目重新合并,distribute被废弃,setuptools依然是Python安装打包的标准方式。

1.2.3 pip

  pip目前包管理的事实标准。构建在setuptools之上,替代easy_install的。同样提供丰富的包管理功能。从Python3.4开始直接包含在安装文件中。

1.2.4 wheel

  wheel格式定义在PEP427中。wheel文件中不包含.pyc文件。提供 bdist_wheel 作为 setuptools 的扩展命令,这个命令可以用来生成新打包格式 wheel。pip 从1.4版本开始 提供了一个 wheel 子命令来安装 wheel 包。当然,需要先安装 wheel 模块。它可以让Python库以二进制形式安装,而不需要在本地编译。

1.2.5 使用setup.py打包
from distutils.core import setupsetup(name='m',      version='1.0',      description='m project',      author='野马',      author_email='17826854776@163.com',      url='https://mp.csdn.net',      packages=['m', 'm.m2', 'm.m2.m21'],  # 会打包最后m21内的所有文件(m21内没有子包了)      # 注意这里只能放包,不会递归打包包内的子包、__init__.py文件和.py文件      )# name名字# version 版本# packages=[] 打包列表,# packages=['m'],指定m,就会把m所有的非目录子模块打包# ['m', 'm.m1.m2.m3'],逐级建立目录,但是只把m的所有非目录子模块打包,把m.m1.m2.m3打包# ['m', 'm.m1', 'm.m1.m2', 'm.m1.m2.m3']# description 描述信息# author 作者# author_email 作者邮件# url 包的主页,可以不写# terminal中,输入 python setup.py build; python setup.py install# 在site-packages中多了一个m包
1.2.5.1 build命令、编译

创建一个build目录:$ python build

  在项目目录下多了build目录,有一个lib子目录,lib下就是模块m的目录了。==m目录下的*.py文件被复制了,但是子目录没有被复制。==build得到的文件,直接拷贝到其他项目就可以使用。

1.2.5.2 install命令、安装

build后就可以install,直接运行。

$ python install
如果没有build,会先build编译,然后安装。

1.2.5.3 sdist命令、分发

sdist命令: $ python sdist

  创建源代码的分发包。产生一个dist目录,里面生成一个带版本号的压缩包。在其他地方解压缩这个文件,里面有setup .py,就可以使用 p y t h o n s e t u p . p y i n s t a l l 安 装 了 , 也 可 以 python setup.py install 安装了,也可以 pythonsetup.pyinstall pip install m-0.1.0.zip直接使用pip安装这个压缩包。
$ python bdist_wininst # 制作windows下的分发包
$ python bdist_rpm # 打包成rpm
  可以把自己写好的模块发布到公共的Pypi上,也可以搭建Pypi私服,供企业内部使用。Pypi里面的模块没有太好的审核机制,不保证安全,请慎重使用。

1.2.6 wheel包
# from distutils.core import setupfrom setuptools import setupsetup(name='m',      version='1.0',      description='m project',      author='野马',      author_email='17826854776@163.com',      url='https://mp.csdn.net',      packages=['m', 'm.m2', 'm.m2.m21'],  # 会打包最后m21内的所有文件(m21内没有子包了)      # 注意这里只能放包,不会递归打包包内的子包和 __init__.py文件和.py文件      )# terminal中,输入 python setup.py build; python setup.py install# 在site-packages中多了一个m包# python setup.py bdist_egg# python setup.py bdist_wheel

2. 插件化开发

2.1 动态导入

运行根据用户需求(提供字符串),找到模块的资源动态加载起来。

2.1.1 内建函数__import__()

import(name, globals=None, locals=None, fromlist=(), level=0)

name,模块名
import语句本质上就是调用这个函数。但是不鼓励直接使用它。建议使用 importlib.import_module() 。
sys = import(‘sys’) 等价于 import sys

# test.py测试模块class A:    def show_me(self):        print('I am A')        # 主模块if __name__ == '__main__':    mod = __import__('test')    cls = getattr(mod, 'A')  # ——> cls = A    cls().show_me()  # I am A
2.1.2 importlib.import_module()

  importlib.import_module(name, package=None)支持绝对导入和相对导入,如果是相对导入,Package必须设置。

# # test.py 测试模块# class A:#     def show_me(self):#         print('I am A')# 主模块import importlibdef plugin_load(plugin_name: str, sep=':'):    m, _, c = plugin_name.partition(sep)    mod = importlib.import_module(m)    cls = getattr(mod, c)    return cls()if __name__ == '__main__':    a = plugin_load('test:A')    a.show_me()  # I am A

2.2 插件化编程技术

2.2.1 依赖的技术

反射:运行时获取类型的信息,可以动态维护类型数据

动态import:推荐使用importlib模块,实现动态import模块的能力
多线程:可以开启一个线程,等待用户输入,从而加载指定名称的模块

2.2.2 加载的时机

什么时候加载合适?

程序启动的时候,还是程序运行中?

  1. 程序启动时
    像pycharm这样的工具,需要很多组件,这些组件也可能是插件,启动的时候扫描固定的目录,加载插件。
  2. 程序运行中
    程序运行过程中,接受用户指令或请求,启动相应的插件
    两种方式各有利弊,如果插件过多,会导致程序启动很慢,如果用户需要时再加载,如果插件太大或者依赖多,插件也会启动慢。所以先加载必须的、常用的插件,其他插件使用时,再动态载入。

2.3 应用

  软件的设计不可能尽善尽美,或者在某些功能上,不可能做的专业,需要专业的客户自己增强。比如Photoshop的滤镜插件。

  Notepad++,它只需要做好一个文本编辑器就可以了,其它增强功能都通过插件的方式提供。拼写检查、HTML预览、正则插件等。
要定义规范,定义插件从哪里加载、如何加载、必须实现的功能等。
接口和插件的区别?
  接口往往是暴露出来的功能,例如模块提供的函数或方法,加载模块后调用这些函数完成功能。接口也是一种规范,它约定了必须实现的功能(必须提供某名称的函数),但是不关心怎么实现这个功能。插件是把模块加载到系统中,运行它,增强当前系统功能,或者提供系统不具备的功能,往往插件技术应用在框架设计中。系统本身设计简单化、轻量级,实现基本功能后,其他功能通过插件加入进来,方便扩展。

转载地址:http://vpfvi.baihongyu.com/

你可能感兴趣的文章
element ui 弹窗在IE11中关闭时闪现问题修复
查看>>
vue 遍历对象并动态绑定在下拉列表中
查看>>
Vue动态生成el-checkbox点击无法选中的解决方法
查看>>
python __future__
查看>>
MySQL Tricks1
查看>>
python 变量作用域问题(经典坑)
查看>>
pytorch
查看>>
pytorch(三)
查看>>
ubuntu相关
查看>>
C++ 调用json
查看>>
nano中设置脚本开机自启动
查看>>
动态库调动态库
查看>>
Kubernetes集群搭建之CNI-Flanneld部署篇
查看>>
k8s web终端连接工具
查看>>
手绘VS码绘(一):静态图绘制(码绘使用P5.js)
查看>>
手绘VS码绘(二):动态图绘制(码绘使用Processing)
查看>>
基于P5.js的“绘画系统”
查看>>
《达芬奇的人生密码》观后感
查看>>
论文翻译:《一个包容性设计的具体例子:聋人导向可访问性》
查看>>
基于“分形”编写的交互应用
查看>>