社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

Python 骚操作,花式导包的 8 种方法

AirPython • 6 年前 • 376 次点击  
点击上方“AirPython”,选择“加为星标
第一时间关注Python技术干货!


今天这篇文章,跟大家分享 Python 中 8 种( 对,你没有听错,就是 8 种)导入模块的方法。

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'

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
'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__''builtins' (built-in)>, '__spec__'None,
'__package__'None'__doc__'None'__name__''__main__',
'sqlalchemy''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
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 是非常有必要的。


最后,想看更多这个系列的朋友,请帮忙 转发文章、或者 点个在看,只有看的人多了,我的更新速度也才能快起来。



留言送书


今日赠书:《Python爬虫技术-深入理解原理、技术与开发》


今日留言主题

聊聊最近遇到的一个编程问题?



推荐阅读


如何用 PyQt5 快速构建一个简单的 GUI 应用

推荐几款优质 Chrome 摸鱼插件,带你畅快划水

为了保护小姐姐的眼睛,我用自动化做了一款语音机器人



Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/62929