翼度科技»论坛 编程开发 python 查看内容

import原理

11

主题

11

帖子

33

积分

新手上路

Rank: 1

积分
33
1.模块(Module)和包(Package)


1.1 理解模块(Module)

理解为是一个py文件


  • module是组织单位,它自己独立构成一个命名空间,它本身是一个Python object
  • 在Python object里面,还可以有很多其他的Python object
  • 实际应用中, module对应的是py文件。
1.2 理解包(Package)

理解为一个文件夹


  • package是一种特殊的module
  • package 几乎和 module 有一样的功能,它只是多了一个path
  • 区分package跟module,是因为在操作系统层级,package往往对应的是一个文件夹(可以有其他的文件夹或者有文件)
  • package里面儿可以有其它的包(subpackage),也可以有模块(module)
2. import都做了哪些事情


  • 1.查找模块文件(通过sys.path可以查看目录的导入顺序)

    • 程序主目录
    • PYTHONPATH 目录
    • 标准链接库目录

  • 2.编译成位码(即pyc文件)
  • 3、执行模块的代码来创建其所定义的变量

    • 导入时,代码是会执行的

3.导入模块(Module)

3-1 查看sys.path目录

如果自定义包没在目录里,可以往目录中添加搜索路径sys.path.append(path)
搜索是从上往下查找,如果中间查到某个包就不会往下查询,尽量把自定义包插入到前面sys.path.insert(0,path)
  1. test_import # 顶层目录
  2. └── a.py
复制代码
  1. ##### a.py
  2. import sys
  3. if __name__ == '__main__':
  4.   print(sys.path)
复制代码
  1. [
  2.   '/Users/test_import',        # 当前执行py文件所在的文件夹
  3.   '/local/Python3/3.8/lib/python38.zip',
  4.   '/local/Python3/3.8/lib/python3.8',
  5.   '/local/Python3/3.8/lib/python3.8/lib-dynload',
  6.   '/local/Python3/3.8/lib/python3.8/site-packages'        # pip install的位置
  7. ]
复制代码
3-2 导入时代码执行

导入模块/包时,会运行代码把它加载到sys.modules缓存起来。
目录
  1. test_import # 顶层目录
  2. ├── a.py
  3. └── b.py
复制代码
python文件
  1. ##### b.py
  2. print('我是b.py')
  3. ##### a.py
  4. import b
  5. import sys
  6. if __name__ == '__main__':
  7.   print(f"1.我是sys.modules: {dict(sys.modules.items())}")
  8.   print(f"2.打印模块: {b}")
  9.   print('3.我是a.py')
复制代码
运行结果
  1. ➜  python3 a.py
  2. 我是b.py
  3. 1.我是sys.modules: {...,'b': <module 'b' from '/Users/test_import/b.py'>}
  4. 2.打印模块: <module 'b' from '/Users/test_import/b.py'>
  5. 3.我是a.py
复制代码
3-3 导入模块的object(from M import obj/func/var)

目录
  1. test_import # 顶层目录
  2. ├── a.py
  3. └── b.py
复制代码
python文件
  1. ##### b.py
  2. class B:
  3. @staticmethod
  4. def get_b():
  5.    print('我是b.py')
  6. ##### a.py
  7. from b import B
  8. import sys
  9. if __name__ == '__main__':
  10.   print(f"1.我是sys.modules: {dict(sys.modules.items())}")
  11.   print(f"2.打印类: {B}")
  12.   print('3.我是a.py')
复制代码
运行结果
  1. ➜  python3 a.py
  2. 我是b.py
  3. 1.我是sys.modules: {...,'b': <module 'b' from '/Users/test_import/b.py'>}
  4. 2.打印类: <class 'b.B'>
  5. 3.我是a.py
复制代码
4.引入包(Package)

在import一个Package会查看Package下面有没有__init__.py文件,没有的话不会运行额外的代码,有的话运行__init__.py
运行__init__.py文件,实际上是开辟了单独的命名空间存放文件内容,然后用这个命名空间来构成一个module(特殊的module)
4-1 查看包信息(import P)

4-1-1 无__init__.py

,只有namespace
目录
  1. test_import # 顶层目录
  2. ├── a.py
  3. └── mypackage
  4.     └── mymodule.py
复制代码
python文件
  1. ##### a.py
  2. import mypackage
  3. if __name__ == '__main__':
  4.   print(mypackage)
  5.   print('我是a.py')
复制代码
运行结果
  1. ➜  python3 a.py
  2. <module 'mypackage' (namespace)>
  3. 我是a.py
复制代码
4-1-2 有__init__.py

,指向具体的__init__.py文件
目录
  1. test_import # 顶层目录
  2. ├── a.py
  3. └── mypackage
  4.     ├── __init__.py
  5.     └── mymodule.py
复制代码
python文件
  1. ##### mypackage/__init__.pyprint('我是mypackage的__init__.py')##### a.py
  2. import mypackage
  3. if __name__ == '__main__':
  4.   print(mypackage)
  5.   print('我是a.py')
复制代码
运行结果
  1. ➜  python3 a.py
  2. 我是mypackage的__init__.py
  3. <module 'mypackage' from '/Users/test_import/mypackage/__init__.py'>
  4. 我是a.py
复制代码
4-2 查看包有没有引入模块(import P)

import package时,查看包下面的模块有没有被导入
4-2-1 无__init__.py

dir(mypackage)中没有mymodule的命名空间
目录
  1. test_import # 顶层目录
  2. ├── a.py
  3. └── mypackage
  4.     └── mymodule.py
复制代码
python文件
  1. ##### a.py
  2. import mypackage
  3. if __name__ == '__main__':
  4.   print(mypackage)
  5.   print(dir(mypackage))
  6.   print('我是a.py')
复制代码
运行结果
  1. <module 'mypackage' (namespace)>
  2. ['__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__']
  3. 我是a.py
复制代码
4-2-2 有__init__.py

dir(mypackage)中mymodule的命名空间
目录
  1. test_import # 顶层目录
  2. ├── a.py
  3. └── mypackage
  4.     ├── __init__.py
  5.     └── mymodule.py
复制代码
python文件
  1. ##### mypackage/__init__.pyclass B:  pass##### a.py
  2. import mypackage
  3. if __name__ == '__main__':
  4.   print(mypackage)
  5.   print(dir(mypackage))
  6.   print('我是a.py')
复制代码
运行结果
  1. ➜  python3 a.py
  2. <module 'mypackage' from '/Users/test_import/mypackage/__init__.py'>
  3. ['B', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__']
  4. 我是a.py
复制代码
4-3 从包中导入模块(import P from M)

4-3-1 无__init__.py

想查看mypackage信息就查看不了了
目录
  1. test_import # 顶层目录
  2. ├── a.py
  3. └── mypackage
  4.     └── mymodule.py
复制代码
python文件
  1. ##### mymodule.py
  2. class Mym:
  3.   ...
  4.   
  5. ##### a.py
  6. from mypackage import mymodule
  7. if __name__ == '__main__':
  8.   # print(mypackage)
  9.   # print(dir(mypackage))
  10.   print(mymodule)
  11.   print(dir(mymodule))
  12.   print('我是a.py')
复制代码
运行结果
  1. ➜  python3 a.py
  2. <module 'mypackage.mymodule' from '/Users/test_import/mypackage/mymodule.py'>
  3. ['Mym', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
  4. 我是a.py
复制代码
4-3-2 有__init__.py(无内容)

目录
  1. test_import # 顶层目录
  2. ├── a.py
  3. └── mypackage
  4.     ├── __init__.py
  5.     └── mymodule.py
复制代码
python文件
  1. ##### mymodule.py
  2. class Mym:
  3.   ...
  4.   
  5. ##### a.py
  6. from mypackage import mymodule
  7. if __name__ == '__main__':
  8.   # print(mypackage)
  9.   # print(dir(mypackage))
  10.   print(mymodule)
  11.   print(dir(mymodule))
  12.   print('我是a.py')
复制代码
运行结果
  1. ➜  python3 a.py
  2. <module 'mypackage.mymodule' from '/Users/test_import/mypackage/mymodule.py'>
  3. ['Mym', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
  4. 我是a.py
复制代码
4-3-3 有__init__.py(有内容)

目录
  1. test_import # 顶层目录
  2. ├── a.py
  3. └── mypackage
  4.     ├── __init__.py
  5.     └── mymodule.py
复制代码
python文件
  1. ##### mymodule.py
  2. class Mym:
  3.   ...
  4.   
  5. ##### __init__.py
  6. mymodule = '我是__init__里的mymodule'
  7. ##### a.py
  8. from mypackage import mymodule
  9. if __name__ == '__main__':
  10.   # print(mypackage)
  11.   # print(dir(mypackage))
  12.   print(mymodule)
  13.   print(dir(mymodule))
  14.   print('我是a.py')
复制代码
运行结果
  1. ➜  python3 a.py            
  2. 我是__init__里的mymodule
  3. [..., 'center', 'count', 'encode', 'endswith', ...]
  4. 我是a.py
复制代码
4-4 直接导入(import P.M)

import mypackage.mymodule时,单独使用mymodule会报错NameError: name 'mymodule' is not defined
必须mypackage.mymodule一起使用
4-4-3 无__init__.py

目录
  1. test_import # 顶层目录
  2. ├── a.py
  3. └── mypackage
  4.     └── mymodule.py
复制代码
python文件
  1. ##### mymodule.py
  2. class Mym:
  3.   ...
  4. ##### a.py
  5. import mypackage.mymodule
  6. if __name__ == '__main__':
  7.   print(mypackage)
  8.   print(dir(mypackage))
  9.   # print(mymodule)        # 报错
  10.   # print(dir(mymodule))        # 报错
  11.   print(mypackage.mymodule)
  12.   print(dir(mypackage.mymodule))
  13.   print('我是a.py')
复制代码
运行结果
  1. ➜  python3 a.py
  2. <module 'mypackage' (namespace)>
  3. ['__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'mymodule']
  4. <module 'mypackage.mymodule' from '/Users/test_import/mypackage/mymodule.py'>
  5. ['Mym', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
  6. 我是a.py
复制代码
4-4-3 有__init__.py(无内容)

效果和没有__init__.py执行是一样的
目录
  1. test_import # 顶层目录
  2. ├── a.py
  3. └── mypackage
  4.     ├── __init__.py
  5.     └── mymodule.py
复制代码
python文件
  1. ##### mymodule.py
  2. class Mym:
  3.   ...
  4. ##### a.py
  5. import mypackage.mymodule
  6. if __name__ == '__main__':
  7.   print(mypackage)
  8.   print(dir(mypackage))
  9.   # print(mymodule)        # 报错
  10.   # print(dir(mymodule))        # 报错
  11.   print(mypackage.mymodule)
  12.   print(dir(mypackage.mymodule))
  13.   print('我是a.py')
复制代码
运行结果
  1. ➜  python3 a.py
  2. <module 'mypackage' from '/Users/test_import/mypackage/__init__.py'>
  3. ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'mymodule']
  4. <module 'mypackage.mymodule' from '/Users/test_import/mypackage/mymodule.py'>
  5. ['Mym', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
  6. 我是a.py
复制代码
4-4-3 有__init__.py(有内容)

目录
  1. test_import # 顶层目录
  2. ├── a.py
  3. └── mypackage
  4.     ├── __init__.py
  5.     └── mymodule.py
复制代码
python文件
  1. ##### mymodule.py
  2. class Mym:
  3.   ...
  4.   
  5. ##### __init__.py
  6. mymodule = '我是__init__里的mymodule'
  7. ##### a.py
  8. import mypackage.mymodule
  9. if __name__ == '__main__':
  10.   print(mypackage)
  11.   print(dir(mypackage))
  12.   # print(mymodule)
  13.   # print(dir(mymodule))
  14.   print(mypackage.mymodule)
  15.   print(dir(mypackage.mymodule))
  16.   print('我是a.py')
复制代码
运行结果
  1. ➜  python3 a.py
  2. <module 'mypackage' from '/Users/test_import/mypackage/__init__.py'>
  3. ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'mymodule']
  4. <module 'mypackage.mymodule' from '/Users/test_import/mypackage/mymodule.py'>
  5. ['Mym', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
  6. 我是a.py
复制代码
5.关于__init__.py

在python3中,文件夹下无论有没有__init__.py文件,这个文件夹都可以作为一个包(Package)被python使用
可以存放和普通模块一样的代码(量、类、函数..)
在__init__.py中使用相对导入
5-1 简化import语法

5-1-1 无__init__.py

需要指名道姓的支出使用哪个obj/func/var
目录
  1. test_import # 顶层目录
  2. ├── a.py
  3. └── mypackage
  4.     └── mymodule.py
复制代码
python文件
  1. ##### mypackage/mymodule.py
  2. class Mym:
  3.   @staticmethod
  4.   def get_mym():
  5.     print('我是Mym的')
  6. ##### a.py
  7. from mypackage.mymodule import Mym
  8. if __name__ == '__main__':
  9.   Mym().get_mym()
复制代码
运行结果
  1. ➜  python3 a.py
  2. 我是Mym的
复制代码
5-1-2 有__init__.py

from p.x.x.x.m import obj转变为from p import obj的效果
目录
  1. test_import # 顶层目录
  2. ├── a.py
  3. └── mypackage
  4.     ├── __init__.py
  5.     └── mymodule.py
复制代码
python文件
  1. ##### mypackage/mymodule.py
  2. class Mym:
  3.   @staticmethod
  4.   def get_mym():
  5.     print('我是Mym的')
  6. ##### mypackage/__init__.py
  7. from .mymodule import Mym
  8. ##### a.py
  9. from mypackage import Mym
  10. if __name__ == '__main__':
  11.   Mym().get_mym()
复制代码
运行结果
  1. ➜  python3 a.py
  2. 我是Mym的
复制代码
5-2 批量导入和规范化导入以及__all__

用于管理导出的方法,只在from p import *是生效
有效: __init__.py使用from m import * 同时a.py使用from p import *时才生效
无效: __init__.py使用from m import * 而a.py使用from p import fun3那么会绕开__all__设置的规则, 可以直接使用fun3
目录
  1. test_import # 顶层目录
  2. ├── a.py
  3. └── mypackage
  4.     ├── __init__.py
  5.     └── mymodule.py
复制代码
python文件
  1. ##### mypackage/mymodule.py
  2. def fun1():
  3.   print('我是fun1')
  4. def fun2():
  5.   print('我是fun2')
  6. def fun3():
  7.   print('我是fun3')
  8. ##### mypackage/__init__.py
  9. from .mymodule import *
  10. __all__ = ['fun1', 'fun2']
  11. ##### a.py
  12. from mypackage import *
  13. if __name__ == '__main__':
  14.   fun1()
  15.   fun2()
  16.   # fun3() 报错NameError: name 'fun3' is not defined
复制代码
运行结果
  1. ➜  python3 a.py
  2. 我是fun1
  3. 我是fun2
复制代码
6.绝对导入和相对导入

6-1 绝对导入

目录
  1. test_import # 顶层目录
  2. ├── a.py        # 引用了b.py和c.py[子孙关系]
  3. ├── p1
  4. │   ├── b.py     # 引用了c.py[长辈关系]
  5. │   └── p11
  6. │       └── c.py # 有一个def run():print('我是c.py')
  7. └── p2
  8.     ├── p21
  9.     │   └── d.py # 引用了e.py[堂兄弟关系]
  10.     └── p22
  11.         └── e.py # 有一个def run():print('我是e.py')
复制代码
文件内容
  1. ##### p1/b.py
  2. from p1.p11 import c
  3. c.run()
  4. ##### p2/p21/d.py
  5. from p2.p22 import e
  6. e.run()
  7. ##### a.py
  8. from p1 import b
  9. from p2.p21 import d
复制代码
6-1-1 绝对-运行主文件(a.py)
  1. ➜  python3 a.py
  2. 我是c.py
  3. 我是e.py
复制代码
6-1-2 绝对-运行子包下面的模块(b.py)
  1. # 在test_import文件夹内调用b.py
  2. ➜  python3 p1/b.py
  3. Traceback (most recent call last):
  4.   File "p1/b.py", line 1, in <module>
  5.     from p1.p11 import c
  6. ModuleNotFoundError: No module named 'p1'
  7. # 进入p1文件夹内运行也报错
  8. ➜  python3 b.py
  9. Traceback (most recent call last):
  10.   File "b.py", line 1, in <module>
  11.     from p1.p11 import c
  12. ModuleNotFoundError: No module named 'p1'
  13. # 使用python3 -m运行(b.py顶层外面执行,p1是共同的顶层)
  14. ➜  python3 -m p1.b
  15. 我是c.py
复制代码
6-1-3 绝对-运行子包下面的模块(d.py)
  1. # 在test_import文件夹内调用d.py
  2. ➜  python3 ./p2/p21/d.py
  3. Traceback (most recent call last):
  4.   File "./p2/p21/d.py", line 1, in <module>
  5.     from p2.p22 import e
  6. ModuleNotFoundError: No module named 'p2'
  7. # 进入p2/p21文件夹运行也报错
  8. ➜  python3 python3 d.py
  9. Traceback (most recent call last):
  10.   File "d.py", line 1, in <module>
  11.     from p2.p22 import e
  12. ModuleNotFoundError: No module named 'p2'
  13. # 使用python3 -m运行(因为是堂兄弟,所以要推到共同顶层外面执行,p2是共同的顶层)
  14. ➜  python3 -m p2.p21.d
  15. 我是e.py
复制代码
6-2 相对导入

目录结构和关系都没有变,只在b.py和 c.py把绝对引入改为相对引入
注意: 入口文件(a.py)不能使用相对引入其他模块,必须为绝对引入
目录
  1. test_import # 顶层目录
  2. ├── a.py        # 引用了b.py和c.py[子孙关系]
  3. ├── p1
  4. │   ├── b.py     # 引用了c.py[长辈关系]
  5. │   └── p11
  6. │       └── c.py # 有一个def run():print('我是c.py')
  7. └── p2
  8.     ├── p21
  9.     │   └── d.py # 引用了e.py[堂兄弟关系]
  10.     └── p22
  11.         └── e.py # 有一个def run():print('我是e.py')
复制代码
文件内容
  1. ##### p1/b.py(改为相对导入)
  2. from .p11 import c
  3. c.run()
  4. ##### p2/p21/d.py(改为相对导入)
  5. from ..p22 import e
  6. e.run()
  7. ##### a.py(主文件不能使用相对导入)
  8. from p1 import b
  9. from p2.p21 import d
复制代码
6-2-1 相对-运行主文件(a.py)
  1. ➜  python3 a.py
  2. 我是c.py
  3. 我是e.py
复制代码
6-2-2 相对-运行子包下面的模块(b.py)
  1. # 在test_import文件夹内调用b.py
  2. ➜  python3 p1/b.py
  3. Traceback (most recent call last):
  4.   File "p1/b.py", line 1, in <module>
  5.     from .p11 import c
  6. ModuleNotFoundError: No module named '__main__.p11'; '__main__' is not a package
  7. # 进入p1文件夹内运行也报错
  8. ➜  python3 b.py
  9. Traceback (most recent call last):
  10.   File "b.py", line 1, in <module>
  11.     from .p11 import c
  12. ModuleNotFoundError: No module named '__main__.p11'; '__main__' is not a package
  13. # 使用python3 -m运行(b.py顶层外面执行,p1是共同的顶层)
  14. ➜  python3 -m p1.b
  15. 我是c.py
复制代码
6-2-3 相对-运行子包下面的模块(d.py)
  1. # 在test_import文件夹内调用d.py
  2. ➜  python3 ./p2/p21/d.py
  3. Traceback (most recent call last):
  4.   File "./p2/p21/d.py", line 1, in <module>
  5.     from ..p22 import e
  6. ValueError: attempted relative import beyond top-level package
  7. # 进入p2/p21文件夹运行也报错
  8. ➜  python3 d.py  
  9. Traceback (most recent call last):
  10.   File "d.py", line 1, in <module>
  11.     from ..p22 import e
  12. ValueError: attempted relative import beyond top-level package
  13. ➜  python3 -m p2.p21.d
  14. 我是e.py
复制代码
7.初步了解python3 -m

mod是module的缩写,即-m后面跟的是模块(module)名,意思是把模块当成脚本来运行。
python3 -m package_name.py_file_name,结尾不需要加.py
1.运行http.server

会把当前文件夹内的文件显示在页面上

  1. ➜  python3 -m http.server 8080
  2. Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
  3. 127.0.0.1 - - [22/Mar/2023 23:56:18] "GET / HTTP/1.1" 200 -
  4. 127.0.0.1 - - [22/Mar/2023 23:56:20] "GET /p1/ HTTP/1.1" 200 -
  5. 127.0.0.1 - - [22/Mar/2023 23:56:22] "GET /p1/p11/ HTTP/1.1" 200 -
  6. 127.0.0.1 - - [22/Mar/2023 23:56:28] "GET /p2/ HTTP/1.1" 200 -
复制代码
来源:https://www.cnblogs.com/lxd670/p/17245970.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具