ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python基础进阶:导入模块的基本操作

2021-01-23 14:01:04  阅读:216  来源: 互联网

标签:func 进阶 python self 模块 import 基本操作 fullname def


本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理

本文章来自腾讯云 作者:Python知识大全

想要学习Python?有问题得不到第一时间解决?来看看这里“1039649593”满足你的需求,资料都已经上传至文件中,可以自行下载!还有海量最新2020python学习资料。
点击查看
在这里插入图片描述

问题

你想给某个已存在模块中的函数添加装饰器。不过,前提是这个模块已经被导入并 且被使用过。

解决方案

这里问题的本质就是你想在模块被加载时执行某个动作。可能是你想在一个模块被加载时触发某个回调函数来通知你。

import importlib
import sys
from collections import defaultdict
_post_import_hooks = defaultdict(list)

class PostImportFinder:
    def __init__(self):
        self._skip = set()
    def find_module(self, fullname, path=None):
        if fullname in self._skip:
     return None
    self._skip.add(fullname)
    return PostImportLoader(self)
    
class PostImportLoader:
  def __init__(self, finder):
    self._finder = finder
  def load_module(self, fullname):
    importlib.import_module(fullname)
    module = sys.modules[fullname]
    for func in _post_import_hooks[fullname]:
      func(module)
      self._finder._skip.remove(fullname)
    return module
    
def when_imported(fullname):
  def decorate(func):
    if fullname in sys.modules:
      func(sys.modules[fullname])
    else:
      _post_import_hooks[fullname].append(func)
    return func
  return decorate
  
sys.meta_path.insert(0, PostImportFinder())

 

这样,你就可以使用 when_imported() 装饰器了

例如:

>>> from postimport import when_imported
>>> @when_imported('threading')
... def warn_threads(mod):
...   print('Threads? Are you crazy?')
...
>>>
>>> import threading
Threads? Are you crazy?
>>>

 

作为一个更实际的例子,你可能想在已存在的定义上面添加装饰器

如下所示:

from functools import wraps
from postimport import when_imported

def logged(func):
  @wraps(func)
  def wrapper(*args, **kwargs):
    print('Calling', func.__name__, args, kwargs)
  return func(*args, **kwargs)
 return wrapper
 
@when_imported('math')
def add_logging(mod):
  mod.cos = logged(mod.cos)
  mod.sin = logged(mod.sin)

 

结论

@when_imported 装饰器的作用是注册在导入时被激活的处理器函数。该装饰器检查 sys.modules 来查看模块是否真的已经被加载了。如果是的话,该处理器被立即调用。不然, 处理器被添加到 _post_import_hooks 字典中的一个列表中去。

_post_import_hooks 的作用就是收集所有的为每个模块注册的处理器对象。一个模块可以注册多个处理器。

要让模块导入后触发添加的动作,PostImportFinder 类被设置为 sys.meta_path 第一个元素。它会捕获所有模块导入操作。

本文中的 PostImportFinder 的作用并不是加载模块,而是自带导入完成 后触发相应的动作。实际的导入被委派给位于 sys.meta_path 中的其他查找器。

PostImportLoader 类中的 imp.import_module() 函数被递归的调用。为了避免陷入无 线循环,PostImportFinder 保持了一个所有被加载过的模块集合。如果一个模块名存 在就会直接被忽略掉。

当一个模块被 imp.import_module() 加载后,所有在 _post_import_hooks 被注 册的处理器被调用,使用新加载模块作为一个参数。有一点需要注意的是本机不适用于那些通过 imp.reload() 被显式加载的模块。也就是说,如果你加载一个之前已被加载过的模块,那么导入处理器将不会再被触发。另 外,要是你从 sys.modules 中删除模块然后再重新导入,处理器又会再一次触发。

标签:func,进阶,python,self,模块,import,基本操作,fullname,def
来源: https://www.cnblogs.com/aa3935919/p/14317473.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有