2015-12-21 124 views
0

我讀過下面的帖子:Python導入,包和運行的腳本

Relative imports for the billionth time

它說明了運行的文件作爲頂級腳本和導入它作爲顯着模塊之間的區別清晰度和細節。

但是我不知道如何編寫一個可運行腳本(if __name__ == '__main__'等等)的導入方式,我也可以從我的測試中導入它,同時保持可運行的狀態腳本獨立(即不需要安裝包)。

說我有以下項目層次:

/reporoot 
    /mypkg 
     /mysubpkg 
      __init__.py 
      subpkgmodule.py 
     __init__.py 
     main1.py 
     main2.py 
    /tests 
     test_main1.py 
     test_main2.py 

test_main1需要以某種方式導入main1,並且main1需要以某種方式導入subpkgmodule。 如果,例如,main1進口subpkgmodule像這樣:

import mysubpkg.subpkgmodule 

這將運行該腳本的頂層腳本時,因爲頂層腳本有其目錄添加到sys.path做工精細。但是,導入模塊時導入會中斷,因爲它的目錄不會被添加到sys.path

如果main1是進口subpkgmodule像這樣:

import mypkg.mysubpkg.subpkgmodule 

當包是一個安裝包(包括python setup.py develop),而不是運行作爲一個獨立的腳本,這隻會工作(即不幹了一些文件系統,運行python main1.py)。

我看到標準庫的http.server模塊有一個import http.client,因此不能像我提到的那樣作爲獨立腳本運行。

對於我的可運行腳本的導入,乾淨的解決方案是什麼?

回答

1

典型的方法是將sys.path放在可運行的腳本中,並將其放在包中。

指定模塊搜索路徑的字符串列表。 從環境變量PYTHONPATH初始化,再加上一個依賴於安裝的默認值 。

在程序啓動時初始化,此列表中的第一項 path [0]是包含用於調用Python解釋器的腳本的目錄。如果腳本目錄不是 可用(例如,如果解釋器是交互式調用的,或者 腳本是從標準輸入讀取的),則path [0]是空字符串, 指示Python首先搜索當前目錄中的模塊。 請注意,在作爲PYTHONPATH的結果插入條目 之前插入了腳本目錄。

程序可以根據自己的目的自由修改此列表。

樣品test_main1.py

import os 
import sys 
sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir)) 

import mypkg.mysubpkg.subpkgmodule # should import fine 

if __name__ == "__main__": 
    pass # runnable code here 
+0

我曾經想過通過一些'testenv'模塊來做這件事,所有的測試都會先導入,但看起來不夠好看 – DoomMuffins

0

庫,如內置unittest有內置的測試發現。默認情況下,它希望測試位於以test*.py模式命名的文件中,其中星號(*)可以是任何您想要的。然後,您會使用discover和使用運行包:

python -m unittest discover 

這假定

  1. 您使用unittest
  2. 你的測試子類unittest.TestCase
  3. 您使用默認類unittest.TestLoader