python 3模塊導入(import)問題一則


      眾所周知,python既可以導入包(import package),也可以導入模塊(import module),package一般理解為多文件的模塊,它是這樣定義的,如果一個目錄下存在”__init__.py”這個文件,那么python就認為這個目錄下的所有文件同屬於一個package(這和java的namespace有點像,但是java可不需要這么個特殊文件),如果沒有這個文件,那么python認為目錄下的py文件都是不相干的獨立模塊。但是在子目錄中你可不能這么干,如果子目錄中沒有”__init__.py”,那么該目錄下的程序算是白寫了,根本沒有辦法引用。當然,也不是絕對的,除非繞個大彎兒:設置當前目錄,然后導入,然后重設當前目錄。比如,程序需要使用test目錄中的模塊,而test目錄不是package,你只能這樣做:

   1: os.chdir("test")
   2: import testfuncs
   3: os.chdir("..")
 
           
         

      最方便的引入,當然是同一個目錄的模塊(除了及其簡單的程序,很少有人會使用這種扁平的目錄結構),那是想怎么導入就怎么導入。比如在主程序中想要使用另一個文件模塊中的函數,只需要直接導入即可:

   1: import testfuncs  #直接導入模塊(也就是不帶擴展名的文件名)
   2: 

3: testfuncs.nousefunc() #通過模塊的名字引用其中的函數

4: from testfuncs import nousefunc #導入模塊中的函數

5: nousefunc() #直接調用導入的函數

 
           
         

      上面只是最簡單的情況,如果文件中定義的是class怎么樣呢,實際使用也是差不多的,不過要多一次構造class的實例的調用:

 

   1: import testclass  #直接導入模塊(也就是不帶擴展名的文件名)
   2: obj=testclass.TestClass(); #實例化類

3: obj.func1() #通過模塊的名字引用其中的class,然后才到類的函數,注意類要實例化

4: from testclass import TestClass #導入模塊中的類

5: obj=TestClass(); #實例化類

6: obj.func1() #調用函數

 
           
         

如果都是這種從程序中引入同目錄或者子目錄的包,那么事情就簡單了,但是如果是同為子目錄中的模塊,要引入兄弟目錄中的模塊或類,要怎么辦呢?例如,如下的目錄結構:

image

圖中src目錄就是程序的頂層目錄,也是包導入的頂層package,pub目錄及其子目錄是公用程序所在。在這種情況下,最好的方法就是在主程序中(一般位於應用的源程序的根目錄,如圖中的start.py),把所有下級的目錄都繳入的sys.path中,然后在子目錄中的模塊中,只要使用完全限定的包名引入其他子目錄中的模塊或者類就可以了。然而現實的情況往往不那么盡如人意,比如為公用包寫的測試程序需要放在pub/test目錄下,測試目標在pub/data目錄下,這是不能寄希望與應用的主程序了,因為此時不會去運行應用程序。這種情況下,啟動程序和被引用的包同在一個父目錄的子目錄中。此時該怎么辦呢,還是老辦法,要把父目錄(src/pub)和(src/pub/data、src/pub/test)目錄都要加入sys.path中,然后再用

絕對的方式進行引入(import pub.data.datautil / from pub.data.datautil import DataUtil)。每一個需要的模塊都要這么干,因此,我特地寫了一個函數,來自動的處理這種情況:

import os,sys
import TestClass
import testfuncs;
from TestClass import TestClass;

def _prepareRelativeImport(layer=2):
    """ 為相對引用做准備,以便下層目錄中的模塊,相對引用[本目錄]以及[父目錄]和[兄弟目錄]中的模塊。
    參數layer,表示引入到多少層父目錄。默認為2->引入本目錄和父目錄;3->引入本目錄、父目錄和祖父目錄。
    """
    import sys,os;
    curP=os.path.abspath(os.path.dirname(__file__)); oriP=curP;__package__=curP.rpartition(os.path.sep)[2];
    print('\r\ncurdir=',curP);
    while layer>=0:
        layer-=1;
        if not curP in sys.path:sys.path.append(curP);
        pa=curP.rpartition(os.path.sep);curN=pa[2];pp=pa[0];os.chdir(pp);
        #if '__init__' in ''.join(os.listdir(curP)):__import__(curN);
        curP=pp;
    os.chdir(oriP);

if __name__=='__main__':
    if not '__file__' in dir():__file__=os.path.abspath('.')+os.path.sep+"1.py";
    _prepareRelativeImport(2)
    from TestClass import TestClass;
    from pub.test.TestClass import TestClass;
    from pub.data.CompareOperator import CompareOperators
    print('\r\nTest of RelativeImport done!')

總結,這么做之后解決了對於測試單個功能或模塊的導入問題,但是在從應用的頂層目錄中運行程序時,還是只能使用Python 3的"from ."來做相對導入,這還真是糾結。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM