2016-03-04 53 views
4

進口進一步混亂我不明白爲什麼以下運行(Python 2.7版),當一個模塊是不是因爲據我瞭解可以用Python

# \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語句被執行時,它不知何故被導入,因爲在wavread.py模塊中有import wavwrite行。我的印象是,這個導入,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有什麼不同?

回答

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

導入子模塊時,還會獲取子模塊的父模塊。

簡單的例子:

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