2011-03-04 48 views
8

我在構建我的python項目時遇到了一些問題。目前它是一堆文件在同一個文件夾中。我試圖把它的結構像測試和python包結構

proj/ 
    __init__.py 
    foo.py 
    ... 
    bar/ 
    __init__.py 
    foobar.py 
    ... 
    tests/ 
    foo_test.py 
    foobar_test.py 
    ... 

問題是,我不能從內部目錄,從外部目錄導入模塊。這對測試尤其惱人。

我已閱讀關於相對進口的PEP 328和關於從主模塊進行的相對進口的PEP 366。但是這兩種方法都需要基礎包裝在我的PYTHONPATH中。事實上,我得到以下錯誤

ValueError: Attempted relative import in non-package.

所以我添加的測試文件

import os, sys 
sys.path.append(os.path.join(os.getcwd(), os.path.pardir)) 

我仍然得到同樣的錯誤的頂部以下樣板代碼。什麼是正確的方式來

  • 結構的包,完成測試,並
  • 增加的基本目錄,以允許進口的路徑?

編輯作爲評論的要求,我想補充一個例子導入失敗

import os, sys 
sys.path.append(os.path.join(os.getcwd(), os.path.pardir)) 
from ..foo import Foo 
+0

可以顯示導入失敗的示例嗎? –

+0

此外,請爲您的'PYTHONPATH' –

+0

'echo $ PYTHONPATH'包含值現在只是空的。 – Andrea

回答

12

當您使用-m切換器來運行代碼時,當前目錄被添加到sys.path。因此,要運行測試的最簡單的方法是從proj父目錄,使用以下命令:

python -m proj.tests.foo_test 

爲了使這項工作,你將需要包括一個__init__.py文件在您的測試目錄中,以便測試是正確的確認爲包裝的一部分。

+0

謝謝!所以我錯過了''測試'本身應該是一個包。這是一個相當愚蠢的錯誤,但我無法弄清楚。 – Andrea

5

我喜歡使用完整的proj.NAME包前綴儘可能導入模塊(文件foo_test.py中)。這是Google Python styleguide推薦的方法。

允許您保留包結構,使用完整包路徑,並繼續前進開發的一個選擇是使用virtualenv並將項目置於開發模式。您的項目setup.py將需要使用setuptools而不是distutils,以獲取develop命令。

這將讓你避免sys.path.append東西上面:

% virtualenv ~/virt 
% . ~/virt/bin/activate 
(virt)~% cd ~/myproject 
(virt)~/myproject% python setup.py develop 
(virt)~/myproject% python tests/foo_test.py 

其中foo_test.py用途:

from proj.foo import Foo 

現在,當你從你的virtualenv您PYTHONPATH中運行python將指向所有的軟件包在你的項目中。你可以創建一個更短的shell別名來輸入你的virtualenv,而不必每次輸入. ~/virt/bin/activate

+0

這似乎很有趣。我將不得不調查這個virtualenv工具。它是否允許我在虛擬環境中工作,以便可以將當前目錄作爲一個包進行訪問?或者它只是一個帶有獨立python發行版的工具 - 更像是一個chroot--我必須在每次使用它之前安裝我的軟件包? – Andrea

+0

這是一種創建獨立Python環境的快速方法,可以快速刪除並重新創建。適合嘗試使用pip/easy_install模塊而不會污染您的系統Python。 virtualenv'activate'腳本將'〜/ virt/bin'目錄插入PATH的前面,以便在系統python之前找到〜/ virt/bin/python。 'develop'命令使用'.pth'文件將項目的包鏈接到'〜/ virt/lib/pythonx.x/site-packages'中。它還修改了'PS1'提示,讓你知道你是在虛擬內部的「內部」。 – samplebias

+0

很好的建議,儘管現在你可能想選擇'distribute'作爲'setuptools'的一個更積極維護的替代品。 – ncoghlan