2

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

import inspect

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

并且剥离最后一部分以获得模块的包也很容易:

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

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

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

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

4

2 回答 2

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'

等等

于 2013-10-08T12:54:19.103 回答
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)

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

于 2013-10-14T09:51:11.080 回答