如果都是这种从程序中引入同目录或者子目录的包,那么事情就简单了,但是如果是同为子目录中的模块,要引入兄弟目录中的模块或类,要怎么办呢?例如,如下的目录结构:
图中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 ."来做相对导入,这还真是纠结。
This work is licensed under a Creative Commons Attribution Non-commercial license.