2016-04-10 191 views
2

TL; DR導入,Python的2.7

對於固定的和不可改變的非封裝的目錄結構是這樣的:

some_dir/ 
    mod.py 
    test/ 
     test_mod.py 
     example_data.txt 

什麼是一個非-package方式使test_mod.pymod.py導入?

我被限制在這種情況下使用Python 2.7。

我想爲mod.py中的函數寫一些測試。我想創建一個新目錄test,它與mod.py並排,並且裏面有一個測試文件test/test_mod.py,它應該從mod.py導入功能並測試它們。

由於相對導入的衆所周知的侷限性,它依賴於基於包的命名,所以不能以直接的方式完成此操作。然而,關於該主題的所有建議都建議將該腳本構建爲一個包,然後使用相對導入,這對我的用例來說是不可能的。

在我的情況下,mod.py不可以作爲一個包來構建,我不能要求mod.py的用戶來安裝它。他們可以自由地僅僅從版本控制中檢查文件,然後開始使用它,但是他們希望,並且我無法改變這種情況。

鑑於此,有什麼方法可以提供簡單,直接的test目錄

注:只是坐在旁邊mod.py測試文件,但實際測試的目錄,因爲會有其他資產一樣,隨之而來的測試數據,和子目錄組織是至關重要的。

我很抱歉如果這是重複的,但是在發佈之前我在研究中看到的這個問題的十幾個排列中,我還沒有看到一個解決如何執行此操作的問題。他們都說要使用包裝,這對我的情況來說不是一個允許的選擇。

+0

也許不是最優雅的解決方案,但您可以爲您的測試跑步者修改'PYTHONPATH'。 。 。 – mgilson

回答

1

根據@mgilson的評論,我在測試目錄中添加了一個文件import_helper.py

some_dir/ 
    mod.py 
    test/ 
     test_mod.py 
     import_helper.py 
     example_data.txt 

這裏是import_helper.py內容:

import sys as _sys 
import os.path as _ospath 
import inspect as _inspect 
from contextlib import contextmanager as _contextmanager 

@_contextmanager 
def enable_parent_import(): 
    path_appended = False 
    try: 
     current_file  = _inspect.getfile(_inspect.currentframe()) 
     current_directory = _ospath.dirname(_ospath.abspath(current_file)) 
     parent_directory = _ospath.dirname(current_directory) 
     _sys.path.insert(0, parent_directory) 
     path_appended = True 
     yield 
    finally: 
     if path_appended: 
      _sys.path.pop(0) 

然後在test_mod.py進口部分,之前試圖導入mod.py來,我說:

import unittest 
from import_helper import enable_parent_import 

with enable_parent_import(): 
    from mod import some_mod_function_to_test 

它不幸的是需要手動修改PYTHONPATH,但是將其作爲上下文管理器寫一點會有所幫助,並將其恢復到其o父目錄修改之前的嚴格狀態。

爲了讓這個解決方案能夠跨越這個問題的多個實例(比如明天我要求爲一些不相關的任務編寫一個widget.py模塊,並且它也不能作爲包分發),我必須複製我的幫助函數並確保它的副本隨測試分發,或者我必須將該小工具編寫爲一個包,確保它在全球範圍內安裝在我的用戶羣中,然後繼續向前發展。

當您管理公司內部的很多Python代碼時,通常會出現一種不正常的代碼分佈模式,即「安裝」某些Python代碼變得相當於從版本控制中檢出新版本。

由於代碼通常非常集中且特定於較小團隊的一小部分子任務的一小部分任務,所以維持通過打包共享代碼的開銷(即使它通常是一個更好的主意)將永遠不會發生。因此,我覺得我上面描述的用例對於真實世界的Python非常常見,如果某些導入工具添加了此功能來修改PYTHONPATH,那麼這將很不錯,目錄)非常容易。

這樣你就可以依靠這個至少成爲標準庫的一部分,而不需要推出你自己的代碼,並確保它隨測試一起提供或安裝在你的用戶基礎上。