2011-07-12 33 views
55

這是一個經常以不同形式提出的問題,並且經常會得到「大聲笑你沒有正確地做它」的反應。可以肯定的是,這是因爲人們(包括我)試圖用作實現有一個常識,而解決方案並不明顯(如果以前沒有這樣做)。使用鼻子進行測試的Python進口 - 當前軟件包的進口模塊的最佳做法是什麼

會接受「讓飛出瓶子」的答案。

鑑於

project/ 
    __init__.py 
    /code 
     __init__.py 
     sut.py 
    /tests 
     __init__.py 
     test_sut.py 

其中tests_sut.py開始:

import code.sut 

在根目錄運行nosetests導致:

ImportError: No module named code.sut 

大道前往:

一)做一個親戚唱

from ..code import sut 

b)增加項目的根PYTHONPATH

C)使用

sys.path.append 

在每個測試模塊的起始進口之前添加..路徑。

d)只記得做一個

setup.py 

對項目運行測試前安裝的模塊到站點包。


所以要求測試位於可以訪問項目的測試包根目錄下。上述每個人對我來說都不覺得「自然」,已經證明存在問題或者看起來像是太辛苦了!

在java中這個工作,但基本上是由你的構建工具/ IDE將所有類放在類路徑上。也許問題是我期待Python的「魔力」?在Flask webframework測試中注意到,選項d)似乎是首選。

在任何情況下,下面推薦一個首選解決方案的陳述都會消除我自己的「不自然」的感覺。

+0

相關http://stackoverflow.com/questions/6323860/sibling-package-imports/6466139#6466139雖然不是一個確切的副本。 – Evpok

+0

這精美地總結了我的情況的80-90% - 如果只是有任何澄清是否virtualenv會改變答案... – sage

回答

8

您已經很好地回答了您的問題。 D(安裝到系統位置)是可分發代碼的首選。我通常使用C(修改sys.path),因爲我不希望我的數百個自定義庫在系統範圍內安裝。從理論上講,A(相對輸入)似乎更好,但有些情況下輸出失敗。 B(PYTHONPATH)是正確的,真的只用於測試目的在我看來。

這幾乎總結了所有的選項。你喜歡的選項(Python神奇地知道在哪裏看)實際上不是一個可行的解決方案,因爲它可能導致不可預知的結果,比如從不相關項目自動查找庫。

在我看來,做的最好的事情就是把這個在入口點(S)到你的程序:

import sys, os 
sys.path = [os.path.abspath(os.path.dirname(__file__))] + sys.path 
+1

但我想我的入口點(s!)是nosetests命令!我認爲在sys.path追加後編寫一個nosetests包裝器調用nose.run的路徑,但它又覺得不自然。感謝這一點,它會幫助我繼續。 – leonigmig

+0

如果您正在通過nosetests測試,那麼入口點就是導入的各個模塊,這將非常尷尬。在這種情況下,您可能會發現PYTHONPATH是最不方便的選項(正如我所說的,可以用於測試目的)。我在這裏感受到你的痛苦 - 我也希望更多的人加入,讓它看起來好(或者提出更好的解決方案)。 – Luke

43

我有同樣的問題和相關問題的工作中發現的answer我。

只需刪除項目根目錄中的__init__.py。

+8

很好的回答!我有一箇舊的\ _ \ _ init \ _ \ _。pyc留下來導致我這個問題。 – frabcus

+0

這並沒有幫助我,這應該如何解決? – user541905

+1

@ user541905:因爲鼻子智能地試圖填充你的'sys.path'。 django-nose本身的一個很好的解釋:https://github.com/django-nose/django-nose#upgrading-from-django--13-to-django-14 – furins

3

我知道有一個答案檢查,我仍然認爲這是一個很好的理由,分享其他替代品:)

有一個nose-pathmunge給你一個控件設置sys.path在調用nosestests