区分模块和包

时间:2013-10-08 12:30:19

标签: python module package

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

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__加上扩展名的文件。但这对我来说似乎很脆弱。

2 个答案:

答案 0 :(得分: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'

答案 1 :(得分:1)

这就是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)

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