2014-06-18 44 views
8

我正在查看兩條__import__語句的代碼,第二條__import__語句不起作用,除非第一條語句已經運行。爲什麼一個__import__語句影響下一個的有效性?

的目錄結構是這樣的:

dir1 
|-__init__.py 
|-subdir1 
| |-__init__.py 
| |-file1.py 
| |-file2.py 
| 
|-subdir2 
    |-__init__.py 
    |-file1.py 
    |-file2.py 

的代碼有兩個__import__聲明:

m = __import__('dir1.'+subdir1, fromlist=[file1]) 
... 
m = __import__(file2, fromlist=[class_inside_file2]) 

第一個是有道理的 - 大致是這樣做

from dir1.subdir1 import file1 
相當於

但允許動態提供子目錄和文件。這是第二種說法,我不明白它爲什麼起作用。它看起來應該是

from file2 import class_inside_file2 

相當於這不應該上班​​是subdir1,但我的當前工作目錄是上面兩個層次。此外,所有__init__.py文件都是空的。

正如您所預料的那樣,如果第二個導入語句自身運行,則第二個導入語句會失敗,並返回ImportError。但是,之後的第一個導入語句已經運行第二個工作。爲什麼?

+0

具有'__import__'s的代碼在哪裏?另外,第二個有'file2'或''file2「'?從你的文章中不清楚哪些東西是變量,哪些是文字串。 – BrenBarn

+0

@BrenBarn @BrenBarn大部分變量都會在代碼評估時保存這些字面值,即'file2'的值爲''file2'''。 –

+0

檢查第一個導入不會覆蓋'file2'的值,它不應該給出您發佈的內容,但我猜這不是實際的代碼。 –

回答

4

這不僅僅是__import__語句,因爲我無法複製此行爲。

$ mkdir -p dir1/subdir1 dir1/subdir2 
$ touch dir1/__init__.py dir1/subdir1/__init__.py dir1/subdir2/__init__.py 
$ echo "print '1.1'" > dir1/subdir1/file1.py 
$ echo "print '1.2'" > dir1/subdir1/file2.py 
$ echo "print '2.2'" > dir1/subdir2/file2.py 
$ echo "print '2.1'" > dir1/subdir2/file1.py 

給出了以下結構:

$ find . -name "*.py" 
./dir1/__init__.py 
./dir1/subdir1/__init__.py 
./dir1/subdir1/file1.py 
./dir1/subdir1/file2.py 
./dir1/subdir2/__init__.py 
./dir1/subdir2/file1.py 
./dir1/subdir2/file2.py 

但是按預期已經發布第二__import__命令失敗:

$ python 
Python 2.7.6 (default, Nov 18 2013, 11:23:24) 
[GCC 4.2.1 Compatible Apple LLVM 4.2 (clang-425.0.24)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> subdir1 = 'subdir1' 
>>> file1 = 'file1' 
>>> m = __import__('dir1.'+subdir1, fromlist=[file1]) 
1.1 
>>> file2 = 'file2' 
>>> class_inside_file2 = '*' 
>>> m = __import__(file2, fromlist=[class_inside_file2]) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ImportError: No module named file2 
+0

只是要發佈相同的東西。 – dano

+3

這不是一個答案。對這個問題發表評論,只說你的第一句話,會更好。 – BrenBarn

+2

@BrenBarn我認爲,但是這允許其他人也嘗試它(例如在不同的平臺上),並在出現錯誤時更正我的過程。爲什麼你覺得信息會更好? –

5

原來的解釋是相當愚蠢的。 file1修改sys.pathsubdir1添加到路徑。通過路徑上的subdir1,它顯然可以直接找到file2,而無需指定任何包。

故事的道德 - 副作用(如導入模塊時發生的事情)是愚蠢的,因爲它經常會導致看起來怪異並且很難診斷的問題。

相關問題