python跨文件调用函数
- 文件组织形式
- 场景1--同文件夹下调用(涉及两个文件)
- 场景2--同文件加下调用(涉及三个文件)
- 场景3--不同文件夹下调用(涉及两个文件)
- 场景4--不同文件夹下调用(涉及三个文件)
文件组织形式
函数调用测试
|---a.py
|---b.py
|---main.py
test
|---c.py
|---d.py
图片展示如下:
每个文件内容如下:
a.py
def a_hello():
print("a_hello")
b.py
from a import a_hello
def b_hello():
print("从b中调用a_hello")
a_hello()
c.py
def c_hello():
print("c_hello")
d.py
from c import c_hello
def d_hello():
print("从d调用c_hello")
c_hello()
场景1–同文件夹下调用(涉及两个文件)
现在main.py文件夹需要调用a.py中的a_hello函数时,直接在程序开头写引用即可:
from a import a_hello
main.py中代码:
from a import a_hello
a_hello()
程序运行结果:
场景2–同文件加下调用(涉及三个文件)
在上述代码中可以看到,b.py文件调用了a.py中的a_hello函数,此时,如果main.py文件想要调用b.py文件中的b_hello函数时,就产生了一个函数调用链:main.py->b.py->a.py
这种情况下,仍然是直接在程序开头写引用即可:
from b import b_hello
main.py中代码:
from b import b_hello
b_hello()
程序运行结果:
场景3–不同文件夹下调用(涉及两个文件)
现在想要从main.py中调用c.py中的c_hello函数,由于c.py在test文件夹中,比较符合正常想法的方法是在程序开头添加上:
from test.c import c_hello
但是这样会报错,程序找不到test.c
此时,需要在test文件夹中新建一个__init__.py文件,用于标识test是一个模块。init.py文件中一般不需要写入内容。
此时,程序即可正常运行
main.py中代码:
from test.c import c_hello
c_hello()
程序运行结果:
场景4–不同文件夹下调用(涉及三个文件)
现在需要在main.py文件中调用d.py中的d_hello函数,此时,又形成了一个函数调用链:main.py->d.py->c.py,并且还是跨文件的函数调用链。如果直接写 from test.d import d_hello ,程序会报错,找不到c模块。这种情况下,即使添加了__init__.py文件也没有用。
该怎么办呢?
这种情况下,需要我们指定python文件的系统路径:
import sys
sys.path.insert(0,"./test")
将test文件夹添加到sys.path中,这样,python程序在执行的过程中,就知道test文件夹的位置,程序可以正常运行。
这种方法虽然可以解决问题,但是在实践中极为脆弱,应尽量避免使用。问题是在于将目录名硬编码到了源代码中。如果代码被移到一个新的位置,会导致维护问题。
更加高明的方法是通过模块精心构造一个绝对路径,方法如下:
import sys
from os.path import abspath, join, dirname
sys.path.insert(0, join(abspath(dirname(__file__)), 'test'))
首先通过os.path.dirname(file)获取当前文件的绝对路径,接着在后面追加当前目录下的test文件夹,接着使用abspath获取test文件夹的绝对路径,最后将路径添加到sys.path中的最前面。
maini.py中代码:
import sys
from os.path import abspath, join, dirname
sys.path.insert(0, join(abspath(dirname(__file__)), 'test'))
from test.d import d_hello
d_hello()
程序运行结果:
值得注意的是,添加sys.path操作需要在调用d中的d_hello之前,首先要添加路径,程序才能够找到相应的文件。