9.pkg_resource模块

1.get_importer(path_item)

    get_importer方法主要返回一个importer对象,当系统缓存sys.path_importer_cache中根据path可以取到时,直接返回,如果取不到则创建一个ImpWrapper的类对象作为importer,并将此值返回,返回对象的类型是pkgutil模块中ImpImporter类的一个实例。ImpWrappe类和ImpImporter类的实现方式是一样的,功能也一致。

def get_importer(path_item):
    """Retrieve a PEP 302 "importer" for the given path item

    If there is no importer, this returns a wrapper around the builtin import
    machinery.  The returned importer is only cached if it was created by a
    path hook.
    """
    try:
        importer = sys.path_importer_cache[path_item]
    except KeyError:
        for hook in sys.path_hooks:
            try:
                importer = hook(path_item)
            except ImportError:
                pass
            else:
                break
        else:
            importer = None

    sys.path_importer_cache.setdefault(path_item,importer)
    if importer is None:
        try:
            importer = ImpWrapper(path_item)
        except ImportError:
            pass
    return importer

2._find_adapter(registry, ob)

    参数registry为pkg_resource模块的全局变量_distribution_finders,其值是一个字典{<class pkgutil.ImpImporter at 0x7f14cd474c80>: <function find_on_path at 0x7f14cd4817d0>,  <type 'object'>: <function find_nothing at 0x7f14cd486230>, <type 'zipimport.zipimporter'>: <function find_in_zip at 0x7f14cd4862a8>},键是对应的对象类型,值为对应的函数对象;ob为ImpImporter类的实例对象。

    其作用是根据ob的属性,从_distribution_finders变量中返回对应的函数对象,判断方法:使用getattr(ob, '__class__', type(ob))方法得到ob实例的类名称,接着使用_get_mro方法,判断ob实例对象的类是否为元类type的实例,如果不是,则为该类添加超类object,并返回该类的object属性,返回值为元组,例如(<class pkgutil.ImpImporter at 0x7f667ab6bc18>, <type 'object'>)。

def _get_mro(cls):
    """Get an mro for a type or classic class"""
    if not isinstance(cls,type):
        class cls(cls,object): pass
        return cls.__mro__[1:]
    return cls.__mro__

def _find_adapter(registry, ob):
    """Return an adapter factory for `ob` from `registry`"""

    for t in _get_mro(getattr(ob, '__class__', type(ob))):
        if t in registry:
            return registry[t]

3._get_mro(cls)

    根据cls的类型,为cls类增加经典类object或None。

def _get_mro(cls):
    """Get an mro for a type or classic class"""
    if not isinstance(cls,type):
        class cls(cls,object): pass
        return cls.__mro__[1:]
    return cls.__mro__

4.find_on_path(importer, path_item, only=False)

    find_on_path根据当前path_item路径过滤出path_item路径的一级路径下,包名以.egg-info或.dist-info结尾的包,并调用Distribution.from_location( path_item,entry,metadata,precedence=DEVELOP_DIST )来返回该包的名称和版本号。

def find_on_path(importer, path_item, only=False):
    """Yield distributions accessible on a sys.path directory"""
    path_item = _normalize_cached(path_item)

    if os.path.isdir(path_item) and os.access(path_item, os.R_OK):
        if path_item.lower().endswith('.egg'):
            # unpacked egg
            yield Distribution.from_filename(
                path_item, metadata=PathMetadata(
                    path_item, os.path.join(path_item,'EGG-INFO')
                )
            )
        else:
            # scan for .egg and .egg-info in directory
            for entry in os.listdir(path_item):
                lower = entry.lower()
                if lower.endswith('.egg-info') or lower.endswith('.dist-info'):
                    fullpath = os.path.join(path_item, entry)
                    if os.path.isdir(fullpath):
                        # egg-info directory, allow getting metadata
                        metadata = PathMetadata(path_item, fullpath)
                    else:
                        metadata = FileMetadata(fullpath)
                    yield Distribution.from_location(
                        path_item,entry,metadata,precedence=DEVELOP_DIST
                    )
                elif not only and lower.endswith('.egg'):
                    for dist in find_distributions(os.path.join(path_item, entry)):
                        yield dist
                elif not only and lower.endswith('.egg-link'):
                    entry_file = open(os.path.join(path_item, entry))
                    try:
                        entry_lines = entry_file.readlines()
                    finally:
                        entry_file.close()
                    for line in entry_lines:
                        if not line.strip(): continue
                        for item in find_distributions(os.path.join(path_item,line.rstrip())):
                            yield item
                        break

5.find_distributions(path_item, only=False)

    调用get_importer(path_item)方法返回一个ImpImporter类的一个实例对象,调用_find_adapter(_distribution_finders, importer)方法,根据importer的类型在_distribution_finders中选择正确的函数。

def find_distributions(path_item, only=False):
    """Yield distributions accessible via `path_item`"""
    importer = get_importer(path_item)
    finder = _find_adapter(_distribution_finders, importer)
    return finder(importer, path_item, only)

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值