我无法理解为什么以下运行(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.wavread
与import wavread
的不同之处?
答案 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.wavwrite
和formats.wavread
都可用。
现在,我正在努力解决这个问题,所以我无法告诉你它为什么会这样设计,这正是我从可用工具中可以看出来的。
答案 1 :(得分:1)
导入子模块时,您还可以获得子模块的父模块。
简单的例子:
>>> numpy
NameError: name 'numpy' is not defined
>>> import numpy.random
>>> numpy
<module 'numpy' from '...\numpy\__init__.pyc'>