包管理、插件化开发

1. 包管理

1.1 为什么实用包管理

  Python的模块或者源文件直接可以复制到目标项目目录中,就可以导入使用了.但是为了更多项目调用使用,或者共享给别人,就需要打包,或发布到网络,以便供人使用。目的也是为了复用。
Pypi(Python Package Index),公共的模块存储中心,https://pypi.python.org/pypi

1.2 主要工具
1.2.1 distutils

  官方库distutils,使用安装脚本setup.py 来构建、安装包。从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 setup

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

1.2.5.2 install命令、安装

build后就可以install,直接运行。
$ python setup.py install
如果没有build,会先build编译,然后安装。

1.2.5.3 sdist命令、分发

sdist命令: $ python setup.py 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 setup.py bdist_wininst # 制作windows下的分发包
$ python setup.py bdist_rpm # 打包成rpm
  可以把自己写好的模块发布到公共的Pypi上,也可以搭建Pypi私服,供企业内部使用。Pypi里面的模块没有太好的审核机制,不保证安全,请慎重使用。

1.2.6 wheel包
# from distutils.core import setup
from setuptools import setup

setup(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 importlib


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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值