zoukankan      html  css  js  c++  java
  • 太酷炫了!!我会Python 导包八种方法,你呢?

    首发于微信公众号:《Python编程时光》
    原文链接:https://mp.weixin.qq.com/s/7F4pyDVObJBt-3XrxxYxLQ

    今天给大家介绍我使用过的 Python 导包的八种方法。

    1. 直接 import

    人尽皆知的方法,直接导入即可

    >>> import os
    >>> os.getcwd()
    '/home/wangbm'
    

    与此类似的还有,不再细讲

    import ...
    import ... as ...
    from ... import ...
    from ... import ... as ...
    

    一般情况下,使用 import 语句导入模块已经够用的。

    但是在一些特殊场景中,可能还需要其他的导入方式。

    下面我会一一地给你介绍。

    2. 使用 _import_

    __import__ 函数可用于导入模块,import 语句也会调用函数。其定义为:

    __import__(name[, globals[, locals[, fromlist[, level]]]])
    

    参数介绍:

    • name (required): 被加载 module 的名称
    • globals (optional): 包含全局变量的字典,该选项很少使用,采用默认值 global()
    • locals (optional): 包含局部变量的字典,内部标准实现未用到该变量,采用默认值 - local()
    • fromlist (Optional): 被导入的 submodule 名称
    • level (Optional): 导入路径选项,Python 2 中默认为 -1,表示同时支持 absolute import 和 relative import。Python 3 中默认为 0,表示仅支持 absolute import。如果大于 0,则表示相对导入的父目录的级数,即 1 类似于 '.',2 类似于 '..'。

    使用示例如下:

    >>> os = __import__('os')
    >>> os.getcwd()
    '/home/wangbm'
    

    如果要实现 import xx as yy 的效果,只要修改左值即可

    如下示例,等价于 import os as myos

    >>> myos = __import__('os')
    >>> myos.getcwd()
    '/home/wangbm'
    

    上面说过的 __import__ 是一个内建函数,既然是内建函数的话,那么这个内建函数必将存在于 __buildins__ 中,因此我们还可以这样导入 os 的模块:

    >>> __builtins__.__dict__['__import__']('os').getcwd()
    '/home/wangbm'
    

    3. 使用 importlib 模块

    importlib 是 Python 中的一个标准库,importlib 能提供的功能非常全面。

    它的简单示例:

    >>> import importlib
    >>> myos=importlib.import_module("os")
    >>> myos.getcwd()
    '/home/wangbm'
    

    如果要实现 import xx as yy效果,可以这样

    >>> import importlib
    >>> 
    >>> myos = importlib.import_module("os")
    >>> myos.getcwd()
    '/home/wangbm'
    

    4. 使用 imp 模块

    imp 模块提供了一些 import 语句内部实现的接口。例如模块查找(find_module)、模块加载(load_module)等等(模块的导入过程会包含模块查找、加载、缓存等步骤)。可以用该模块来简单实现内建的 __import__ 函数功能:

    >>> import imp
    >>> file, pathname, desc = imp.find_module('os')
    >>> myos = imp.load_module('sep', file, pathname, desc)
    >>> myos
    <module 'sep' from '/usr/lib64/python2.7/os.pyc'>
    >>> myos.getcwd()
    '/home/wangbm'
    

    从 python 3 开始,内建的 reload 函数被移到了 imp 模块中。而从 Python 3.4 开始,imp 模块被否决,不再建议使用,其包含的功能被移到了 importlib 模块下。即从 Python 3.4 开始,importlib 模块是之前 imp 模块和 importlib 模块的合集。

    5. 使用 execfile

    在 Python 2 中有一个 execfile 函数,利用它可以用来执行一个文件。

    语法如下:

    execfile(filename[, globals[, locals]])
    

    参数有这么几个:

    • filename:文件名。
    • globals:变量作用域,全局命名空间,如果被提供,则必须是一个字典对象。
    • locals:变量作用域,局部命名空间,如果被提供,可以是任何映射对象。
    >>> execfile("/usr/lib64/python2.7/os.py")
    >>> 
    >>> getcwd()
    '/home/wangbm'
    

    6. 使用 exec 执行

    execfile 只能在 Python2 中使用,Python 3.x 里已经删除了这个函数。

    但是原理值得借鉴,你可以使用 open ... read 读取文件内容,然后再用 exec 去执行模块。

    示例如下:

    >>> with open("/usr/lib64/python2.7/os.py", "r") as f:
    ...     exec(f.read())
    ... 
    >>> getcwd()
    '/home/wangbm'
    

    7. import_from_github_com

    有一个包叫做 import_from_github_com,从名字上很容易得知,它是一个可以从 github 下载安装并导入的包。为了使用它,你需要做的就是按照如下命令使用pip 先安装它。

    $ python3 -m pip install import_from_github_com
    

    这个包使用了PEP 302中新的引入钩子,允许你可以从github上引入包。这个包实际做的就是安装这个包并将它添加到本地。你需要 Python 3.2 或者更高的版本,并且 git 和 pip 都已经安装才能使用这个包。

    pip 要保证是较新版本,如果不是请执行如下命令进行升级。

    $ python3 -m pip install --upgrade pip
    

    确保环境 ok 后,你就可以在 Python shell 中使用 import_from_github_com

    示例如下

    >>> from github_com.zzzeek import sqlalchemy
    Collecting git+https://github.com/zzzeek/sqlalchemy
    Cloning https://github.com/zzzeek/sqlalchemy to /tmp/pip-acfv7t06-build
    Installing collected packages: SQLAlchemy
    Running setup.py install for SQLAlchemy ... done
    Successfully installed SQLAlchemy-1.1.0b1.dev0
    >>> locals()
    {'__builtins__': <module 'builtins' (built-in)>, '__spec__': None,
    '__package__': None, '__doc__': None, '__name__': '__main__',
    'sqlalchemy': <module 'sqlalchemy' from '/usr/local/lib/python3.5/site-packages/
    sqlalchemy/__init__.py'>,
    '__loader__': <class '_frozen_importlib.BuiltinImporter'>}
    >>>
    

    看了 import_from_github_com的源码后,你会注意到它并没有使用importlib。实际上,它的原理就是使用 pip 来安装那些没有安装的包,然后使用Python的__import__()函数来引入新安装的模块。

    8. 远程导入模块

    我在这篇文章里(深入探讨 Python 的 import 机制:实现远程导入模块),深入剖析了导入模块的内部原理,并在最后手动实现了从远程服务器上读取模块内容,并在本地成功将模块导入的导入器。

    具体内容非常的多,你可以点击这个链接进行深入学习。

    示例代码如下:

    # 新建一个 py 文件(my_importer.py),内容如下
    import sys
    import importlib
    import urllib.request as urllib2
    
    class UrlMetaFinder(importlib.abc.MetaPathFinder):
        def __init__(self, baseurl):
            self._baseurl = baseurl
    
    
        def find_module(self, fullname, path=None):
            if path is None:
                baseurl = self._baseurl
            else:
                # 不是原定义的url就直接返回不存在
                if not path.startswith(self._baseurl):
                    return None
                baseurl = path
    
            try:
                loader = UrlMetaLoader(baseurl)
                return loader
            except Exception:
                return None
    
    class UrlMetaLoader(importlib.abc.SourceLoader):
        def __init__(self, baseurl):
            self.baseurl = baseurl
    
        def get_code(self, fullname):
            f = urllib2.urlopen(self.get_filename(fullname))
            return f.read()
    
        def get_data(self):
            pass
    
        def get_filename(self, fullname):
            return self.baseurl + fullname + '.py'
    
    def install_meta(address):
        finder = UrlMetaFinder(address)
        sys.meta_path.append(finder)
    

    并且在远程服务器上开启 http 服务(为了方便,我仅在本地进行演示),并且手动编辑一个名为 my_info 的 python 文件,如果后面导入成功会打印 ok

    $ mkdir httpserver && cd httpserver
    $ cat>my_info.py<EOF
    name='wangbm'
    print('ok')
    EOF
    $ cat my_info.py
    name='wangbm'
    print('ok')
    $
    $ python3 -m http.server 12800
    Serving HTTP on 0.0.0.0 port 12800 (http://0.0.0.0:12800/) ...
    ...
    

    一切准备好,验证开始。

    >>> from my_importer import install_meta
    >>> install_meta('http://localhost:12800/') # 往 sys.meta_path 注册 finder
    >>> import my_info  # 打印ok,说明导入成功
    ok
    >>> my_info.name  # 验证可以取得到变量
    'wangbm'
    

    好了,8 种方法都给大家介绍完毕,对于普通开发者来说,其实只要掌握 import 这种方法足够了,而对于那些想要自己开发框架的人来说,深入学习__import__以及 importlib 是非常有必要的。

  • 相关阅读:
    手机号码正则表达式
    POJ 3233 Matrix Power Series 矩阵快速幂
    UVA 11468
    UVA 1449
    HDU 2896 病毒侵袭 AC自动机
    HDU 3065 病毒侵袭持续中 AC自动机
    HDU 2222 Keywords Search AC自动机
    POJ 3461 Oulipo KMP模板题
    POJ 1226 Substrings KMP
    UVA 1455 Kingdom 线段树+并查集
  • 原文地址:https://www.cnblogs.com/wongbingming/p/12909578.html
Copyright © 2011-2022 走看看