目录结构
C:\USERS\EVILMASS\DESKTOP\PATH0
│ server.py
├───path1
│ │ func.py
│ │ __init__.py
└───path2
│ func.py
│ __init__.py
├───path2_1
│ │ func.py
│ │ __init__.py
│ ├───path2_1_1
│ │ │ func.py
│ │ │ special.py
│ │ │ __init__.py
__init__.py
一个 module1.py 文件可以看作一个模块:import module1,__init__.py 则是将一个文件夹变为 package,每一次 import 都会执行 __init__.py 内的代码。
1
2
3
4
5
6
7
8
|
# no __init__.py
from path2.path2_1.func import echo
from path2.path2_1.special import echo_special
# has __init__.py
from .func import *
from .special import *
from path2.path2_1 import echo, echo_special
|
sys.path
实际遇到的绝大部分问题都是引用路径和循环引用问题,添加临时引用可以解决但请使用:
绝对路径!
绝对路径!
绝对路径!
临时引用
针对不频繁调用的模块可以在入口处添加临时引用
1
2
3
4
5
6
7
8
|
import sys
from os.path import abspath, join, dirname
# 添加临时引用目录
sys.path.append(join(abspath(dirname(__file__)), "path2/path2_1/path2_1_1"))
from special import echo_special
echo_special()
>>> echo_special from: C:\Users\Evilmass\Desktop\path0\path2\path2_1\path2_1_1
|
路径引用问题
path0\path2\path2_1\path2_1_1\special.py 调用同级 text 文件夹下的 echo 模块
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
# path0\path2\path2_1\path2_1_1\__init__.py
from .func *
# path0\path2\path2_1\path2_1_1\special.py\text\__init__.py
from .func *
# path0\path2\path2_1\path2_1_1\special.py
import func
from func import echo as local_echo
import text
from text.func import echo as text_echo
def echo_special():
func.echo()
local_echo()
text.echo()
text_echo()
if __name__ == "__main__":
echo_special()
# path0\server.py 导入 echo_special 会报错,即便有 text.__init__.py
from path2.path2_1.path2_1_1.special import echo_special
echo_special()
Traceback (most recent call last):
File "server.py", line 27, in <module>
from path2.path2_1.path2_1_1.special import echo_special
File "C:\Users\Evilmass\Desktop\path0\path2\path2_1\path2_1_1\__init__.py", line 2, in <module>
from .special import *
File "C:\Users\Evilmass\Desktop\path0\path2\path2_1\path2_1_1\special.py", line 5, in <module>
from text.func import echo as text_echo
ModuleNotFoundError: No module named 'text'
|
但直接在 path2_1_1 目录下执行 python special.py 是正常运行的。
1
2
3
4
5
6
|
cd C:\Users\Evilmass\Desktop\path0\path2\path2_1\path2_1_1
python special.py
>>> echo from: C:\Users\Evilmass\Desktop\path0\path2\path2_1\path2_1_1
>>> echo from: C:\Users\Evilmass\Desktop\path0\path2\path2_1\path2_1_1
>>> echo from: C:\Users\Evilmass\Desktop\path0\path2\path2_1\path2_1_1\text
>>> echo from: C:\Users\Evilmass\Desktop\path0\path2\path2_1\path2_1_1\text
|
错误示范
1
2
3
4
5
6
7
8
9
10
|
# 多了一个 `.` 能让 `server.py` 跑起来
from .text.func import echo as text_echo
# 但在 path2_1_1 目录下运行则会报错
cd C:\Users\Evilmass\Desktop\path0\path2\path2_1\path2_1_1
python special.py
>>> Traceback (most recent call last):
>>> File "special.py", line 5, in <module>
>>> from .text.func import echo as text_echo
>>> ImportError: attempted relative import with no known parent package
|
sys.path
绝大部分问题只要检查一下 sys.path 就能解决
1
2
3
4
5
6
|
import sys
print(sys.path)
>>>['C:\\Users\\evimo\\AppData\\Local\\Programs\\Python\\Python37\\DLLs',
'C:\\Users\\evimo\\AppData\\Local\\Programs\\Python\\Python37\\lib',
'C:\\Users\\evimo\\AppData\\Local\\Programs\\Python\\Python37',
'C:\\Users\\evimo\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages']
|
很明显没有 text 目录,那么 server.py 加临时引用试试。
1
2
3
4
5
6
7
8
|
import sys
from os.path import abspath, join, dirname
# 添加临时引用目录
sys.path.append(join(abspath(dirname(__file__)), "path2/path2_1/path2_1_1/text"))
from path2.path2_1.path2_1_1.special import echo_special
echo_special()
>>>
|
问题解决。
if name == “main”
- 如果作为脚本直接运行,会执行
__name__ == "__main__" 下面的内容
- 如果是被其他
py 文件作为 package 引用则不执行
99% 的文章都会这么告诉你,少部分提一下 ___name__ 作用域,我的建议是:
Talk Is Cheap, Show Me Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# echo.py
def echo():
print(__name__)
if __name__ == "__main__":
echo()
print("after echo, run this")
>>> "__main__"
>>> "after echo, run this"
# another.py
from echo import echo
print(echo.__name__)
>>> "echo"
|