进一步混淆Python中的导入

时间:2016-03-04 09:31:33

标签: python import namespaces

我无法理解为什么以下运行(Python 2.7)时,据我所知,其中一个模块未导入

# \sound\formats\script.py
import formats.wavread

print formats.wavread.foo()
print formats.wavwrite.boo()

我的目录结构是

sound\
    __init__.py
    formats\
       __init__.py
        script.py
        wavread.py
        wavwrite.py

__init__.py都是空的。其余的代码如下

# \sound\formats\wavread.py
import wavwrite # <-- unused import

def foo():
    return "read foo"


# \sound\formats\wavwrite.py
def boo():
    return "write boo"
尽管我的理解中没有导入模块script.py,但

wavwrite.py运行正常。但是,我猜不过它是在执行import formats.wavread语句时导入的,因为import wavwrite模块中有wavread.py行。我的印象是这个导入import wavwrite完全没用,但它会绑定到wavread模块的全局命名空间。因此,wavwrite.boo()方法将超出范围,并且无法从script.py内部访问。显然它不会那样工作。

script.py模块的代码中删除子包前缀看起来使程序按预期工作。因此,如果您运行以下

#\sound\formats\script.py
import wavread

print wavread.foo()
print wavwrite.boo()

将通过打印读取foo来执行wavread.foo()方法,并在下一行删除消息NameError: name 'wavwrite' is not defined时发生错误,因为正如预期的那样wavwrite模块尚未导入

这里到底发生了什么以及import formats.wavreadimport wavread的不同之处?

2 个答案:

答案 0 :(得分:1)

import wavread的简单情况正在发挥作用,因为您的脚本与wavread.py位于同一目录中,因此它只导入该文件。如果您的脚本位于其他目录中,则无法找到wavread.py

下一个案例,让我们看看我们能解决什么问题。您的目录结构类似于Python module tutorial中的目录结构,所以让我们使用那里提到的内置dir(),它将显示范围的内容。例如:

>>> import formats.wavread
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'formats']

# ... new session

>>> from formats import wavread
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'wavread']

因此我们可以看到import formats.wavread也导入父命名空间,因为我们在那里有formats。在第二个示例中,我们只加载一个特定的子模块,因此直接添加到我们的命名空间,而不是formats。对此进行快速测试是向formats/__init__.py添加打印语句 - 当您运行import formats.wavread时,将打印出来:

$ cat formats/__init__.py
print("formats __init__.py")
$ python -m formats.wavread -c ""
formats __init__.py

自导入formats后,formats.wavwriteformats.wavread都可用。

现在,我正在努力解决这个问题,所以我无法告诉你它为什么会这样设计,这正是我从可用工具中可以看出来的。

答案 1 :(得分:1)

导入子模块时,您还可以获得子模块的父模块。

简单的例子:

>>> numpy
NameError: name 'numpy' is not defined
>>> import numpy.random
>>> numpy
<module 'numpy' from '...\numpy\__init__.pyc'>