【问题标题】:How to check submodules in Python with hasattr如何使用 hasattr 检查 Python 中的子模块
【发布时间】:2010-07-13 12:55:26
【问题描述】:

在运行时,Python 代码获取要加载的子模块的名称,这是我以前不知道的。现在,我想检查这个子模块是否存在于现有模块中。考虑这种结构,其中可以指定foobar

master/
|
|- __init__.py
|
|- foo/
|  |
|  |- __init__.py
|
|- bar/
   |
   |- __init__.py

现在,我通常这样做,它适用于 defs 和变量:

import master

unknown_submodule = "foo"
if hasattr(master, unknown_submodule):
    pass # all's well

或者我正在捕获 AttributeError,它同样有效。

但是,对于上述文件结构,我无法启动并使用这种方法。 hasattr() 总是返回 False(即总是抛出 AttributeError)。

如果我查看dir(master),我会看到以下输出:

['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__']

甚至在master/__init__.py 中明确指定__all__ 也无济于事,而是将 dir() 更改为

['__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__']

任何想法,我做错了什么,或者是否有办法实现这些测试? (顺便说一句:Win/Cygwin 上的 Python 2.6,如果有兴趣的话)

【问题讨论】:

    标签: python import module hasattr


    【解决方案1】:

    除非明确说明,否则子模块不是其父模块的属性。只需尝试导入模块并捕获ImportError

    try:
        __import__("os.peth", fromlist=[os])
    except ImportError:
        pass
    

    【讨论】:

    • “明确说明”是什么意思?我想,这就是__all__ 的用途?您是否碰巧手头有一个有用的解释指针? (docs.python.org/tutorial/modules.htmleffbot.org/zone/import-confusion.htm 除外)除此之外,是的,__import__() 可以满足要求。
    • 不,__all__ 确定当您说 from ... import * 时导入的内容。但这与您的问题无关。如果您有一个模块A 和一个模块A.B,那么导入A 并不会神奇地将成员B 添加到A — 仅当A 本身导入A.B 时。要访问A.B,您必须导入A.B,而不是A。在os.path 的情况下,导入os 有效,因为os 确实主动导入os.path
    • 感谢您的解释!我想我开始掌握这件事了。
    【解决方案2】:

    我最近不得不检查子模块的存在,因为我使用的是 python 3.4.1,所以我对这个问题给出了一个新的答案:

    在 python 3.4.1 中你可以使用importlib.util.find_spec(name, package=None) (https://docs.python.org/3.4/library/importlib.html#importlib.util.find_spec)

    import importlib
    module_exists = importlib.util.find_spec('path.to.my.module')
    

    就这么简单=)

    【讨论】:

      【解决方案3】:

      你可以的

      try:
       import module.submodule
      
      except ImportError:
        print 'failed or whatever'
      

      【讨论】:

      • 如果master/__init__.py 没有主动导入master.foo,那么master 就没有名为foo 的成员。如果只导入master,那么master.foo 会引发AttributeError,而不管master.foo 是否存在。
      猜你喜欢
      • 1970-01-01
      • 2013-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-10
      • 2022-06-20
      • 1970-01-01
      • 2013-04-09
      相关资源
      最近更新 更多