【问题标题】:Distinguish modules from packages区分模块和包
【发布时间】:2013-10-15 09:03:30
【问题描述】:

我需要一个函数,它返回调用该函数的模块的 的名称。获取模块名称很简单:

import inspect

module_name = inspect.currentframe().f_back.f_globals['__name__']

并且剥离最后一部分得到模块的包也很简单:

package_name = '.'.join(module_name.split('.')[:-1])

但如果函数是从包的__init__.py 调用的,则不应剥离名称的最后一部分。例如。如果从foo/bar/__init__.py调用,上例中的module_name会被设置为'foo.bar',这已经是包名了。

如何从模块名称或模块对象中检查它是指包还是模块?

我发现最好的方法是获取模块对象的__file__ 属性(如果存在),并检查它是否指向名称为__init__ 加上扩展名的文件。但这对我来说似乎很脆弱。

【问题讨论】:

    标签: python module package


    【解决方案1】:

    来自模块对象:

    module.__package__
    

    适用于我看过的一对夫妇,而且似乎是正确的。不过,它可能无法完全满足您的需求:

    import os.path
    import httplib2
    import xml.etree.ElementTree as etree
    
    os.path.__package__
    <blank... this is a builtin>
    httplib2.__package__
    'httplib2'
    etree.__package__
    'xml.etree'
    

    你可以使用

    function.__module__
    

    还有,但这给你的是模块名称,而不是实际的模块 - 不确定是否有比再次导入局部变量更简单的方法来获取模块对象本身。

    etree.parse.__module__
    'xml.etree.ElementTree'
    
    os.path.split.__module__
    'ntpath'
    

    好在这似乎更正确,遵循事物的实际位置,例如:

    httplib2.Response.__module__
    'httplib2'
    httplib2.copy.copy.__module__
    'copy'
    httplib2.urlparse.ParseResult.__module__
    'urlparse'
    

    等等

    【讨论】:

    • 它似乎做我想做的事。它记录在PEP 366 中,其中指出模块可以将其__package__ 属性设置为空字符串以禁用相对导入。因为我只需要它为我控制的模块工作,所以这不是问题。
    • 抱歉,您的解决方案根本不起作用。据我所知,package 仅设置在看似随机的模块子集上,即使在同一个包中也是如此。我查看并发布了importlib 使用的算法,目前有效。
    • 我上一条评论中的粗体字当然是标记失败,package应该是__package__
    【解决方案2】:

    这就是importlib.__import__()所做的,需要重新实现大部分Python内置的导入逻辑,需要找到一个模块的包来支持相对导入:

    # __package__ is not guaranteed to be defined or could be set to None
    # to represent that it's proper value is unknown
    package = globals.get('__package__')
    if package is None:
        package = globals['__name__']
        if '__path__' not in globals:
            package = package.rpartition('.')[0]
    module = _gcd_import(name, package, level)
    

    所以似乎没有可靠的“直接”方式来获取模块的包。

    【讨论】:

      猜你喜欢
      • 2021-08-28
      • 1970-01-01
      • 2011-04-10
      • 2010-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-18
      相关资源
      最近更新 更多