在看Transformers源码时,在modeling_llama.py中有以下代码
from ...activations import ACT2FN
from ...modeling_outputs import BaseModelOutputWithPast, CausalLMOutputWithPast, SequenceClassifierOutputWithPast
发现用了相对引用,引用了前2级目录下的activations文件,直接运行这个modeling_llama.py代码时报错:
ImportError: attempted relative import with no known parent package
表示程序并没找到父目录。
经过查找原因知道,程序运行时需要以当前运行的__name__变量确定目录。此时运行的__name__为modeling_llama(因为相当于将modeling_llama作为了主函数,本来不是),在跑到…时程序不知道上级和上上级目录是什么(因为只有一个modeling_llama),如果想要跑通,需要在modeling_llama.py的import之前指定__name__=‘xxx/xxx/xxx/modeling_llama.py’,第一个xxx表示modeling_llama.py的前2级目录(不包括目前这一级)。完成__name__之后,还需要让程序知道第一个xxx在哪,这时需要用sys.path.append(yyy)指定第一个xxx的父目录(即xxx在yyy里面,yyy为绝对路径)。
这里写一个具体的例子,以下是目录结构:
|-- Test
| |-- __init__.py
| |-- m4.py
| `-- pkg
| |-- __init__.py
| |-- m2.py
| |-- m3.py
| `-- subpkg
| |-- __init__.py
| `-- m1.py
|-- __init__.py
`-- main_cx.py
main_cx是要运行的主文件,m1,m2,m3,m4分别都是main_cx要调用的函数文件,其中m3和m4内容形式是:
def f3():
print("this is f3 in m3")
m2内容为
from .m3 import f3
def f2():
print("this is f2 in m2")
若m1要调用m2,m3,m4的函数,最后主程序main_cx.py调用m1,此时m1为
def f1():
print("this is f1 in m1")
print(__name__)
from ..m2 import f2,f3
from ...m4 import f4
在主程序main_cx中调用m1的所有方法:
from Test.pkg.subpkg.m1 import f1,f2, f3,f4
print(__name__)
f1()
f2()
f3()
f4()
成功运行输出结果为:
__main__
this is f1 in m1
this is f2 in m2
this is f3 in m3
this is f4 in m4
一半来说,项目会有个主程序来运行,不会出现在相同路径下使用相对引用来导包,所以指定__name__和添加path的方法一般不用(不然太麻烦了)。
【注意】如果主函数调用程序都使用了相对引用,并引用了和主函数同一级下的一个方法。应该把那一行相对引用改为绝对引用,比如m1引用的m4和main_cx在同一级目录,那m1的from …m4 import f4要改成 from m4 import f4,因为运行主函数时能直接调用m4。
参考资料:https://www.bilibili.com/video/BV1EK411g7Ff/?spm_id_from=333.337.search-card.all.click&vd_source=6b23f47ec0d092b0587d7d866c9db443