概述
文章目录
- 概念明确
- 1.1 模块
- 1.2 包
- 1.3 库
- import 导入机制
- import 模块 语法
- from 模块 import 变量 语法
- 相对导入语法
- 循环依赖错误
- 与java的import对比
- 自有项目内的模块 import
- PYTHONPATH
- 参考
模块, 包, 库的概念经常被混用. 只有明确概念, 指代清晰, 才能顺畅遨游python世界.
概念明确
1.1 模块
源文件即模块. 内含若干个类,函数,变量 (因为py不是完全的面向对象).
xxxmodule.__file__
# 查看模块的文件位置(绝对路径).
dir('xxxmodule')
#查看模块中的函数等
自己写一个py源文件, 它的名字就是模块名, 可以被其他源文件 import .
1.2 包
包是一个含有__init__.py
模块的特殊目录, 且内含若干个模块和若干个子目录.
__init__.py
可以只是一个空文件,但是必须存在; 否则就仅仅是普通目录,不能被其他模块导入与依赖.
有些IDE可能会不作严格检查, 但为了各个环境都能预期工作, 还是要确保.
所以包有两种角色: 包目录 与 包模块.
1.3 库
库是相关包的集合. 如numpy
, tensorflow
.
import 导入机制
每种编程语言都有 import 机制来完成对 {类,变量,函数} 的依赖.
import 模块 语法
- import 包模块 [as 别名]
- import 包目录.子包目录.子包目录.包模块 [as 别名]
引入依赖是为了编码使用, 使用时的语法是 x=模块.变量
仔细揣摩一下两块代码片.
# import 片段1
import a
# 引入的是 a/__init__.py, 会找变量b
# 情况1, b是模块, 即 __init__.py 中有 from xx import b, 那找的就是b模块下的c
# 情况2, b是类, 那找的就是b类的成员变量
a.b.c
典型的例子是
import numpy as np
# numpy/__init__.py 中有from . import random
np.random
–分隔–
# import 片段2
import a.b.c
# 引入的是 /a/b/c/__init__.py
a.b.c
Q: __init__.py
中的变量与子目录重名怎么办?
A: todo.
from 模块 import 变量 语法
为了编码时不再写长长的模块名, 可以用 from…import… 语法.
- from 模块 import 类/方法/变量 [as 别名]
- from 目录.子目录.子目录.模块 import 类/方法 [as 别名]
此时使用时的语法是x=变量
- from 目录.子目录.子目录.模块 import *
引入模块下所有变量.
当模块有__all__=[ 'var1','var2']
变量时, 只会导入指定的变量.
pep
标准推荐使用第一种方式,请在日常使用中尽量使用第一种方法,就比如numpy中random 标准库中也有random,但是两者的功能是不同的,使用第二种方式容易造成混淆.
相对导入语法
形如 from . import B
或 from ..A import B
,理解为从 工作目录 作相对路径的导入.
.
代表当前模块,..
代表上层模块,...
代表上上层模块,依次类推。
循环依赖错误
多个模块间使用from xx import xx
这种语法引入循环依赖时, 会报错, 因为解释器都还没有执行到函数定义的代码,所以找不到模块。
解决办法为 使用 import xx
的语法, 不以from xx
打头.
与java的import对比
- import 语法
java导入的只能是类, 清晰且严格.
python 可以引入包,模块,类,方法,易混淆. - import 运行机制
java只是声明一下用到的类的地址. 并没有把类的定义搬过来的效果.
python 的import, 有着把引用的模块搬到了当前源文件里的效果. 这是一个我不喜欢的地方.
比如 A 模块有了import numpy as np
的语句, 那么B模块import A
, 就可以通过A.np
用 np 模块了, 别人看的时候就根本不知道np是一个顶级的包了.
自有项目内的模块 import
建议入口文件在 项目根目录下.
因为
- python解释器会将入口文件所在的目录自动添加到 PYHTONPATH .
- IDE 设置也方便.
PYTHONPATH
上文只是讲语法, 从哪里找要导入的模块呢? 从 PYTHONPATH 中找.
PYTHONPATH 并不是OS的环境变量, 我只知道对应着 sys.path:List[str]
, 通常已经包含['Anaconda3/DLLs','Anaconda3/lib/site-packages']
,还可以自己扩充.
当执行 python a/b/c.py
时, 会自动讲 源文件所在目录加入到 PYTHONPATH 中.
当项目中的一些 test, utils 脚本不在项目根目录下, 但也有执行需求时, 怎么办呢?
- 源码中变更 PYTHONPATH
import os, sys current_path = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, os.path.join(current_path, '../../'))
- 启动命令中加入 PYTHONPATH (linux)
将 PYTHONPATH=xx 和 python x.py 写在一行内. 见参考$ echo $PYTHONPATH $ python -c 'import sys;print("/tmp/pydir" in sys.path)' False $ PYTHONPATH=/tmp/pydir python -c 'import sys;print("/tmp/pydir" in sys.path)' True $ echo $PYTHONPATH
tips
避免与操作系统的 PATH 混淆,
它代表的是可执行文件的寻找目录, py中可通过 os.environ['PATH']
读写.
参考
- s.o.f. add PYTHONPATH during command line module run
最后
以上就是尊敬刺猬为你收集整理的py “类,模块,包与库“ 的 import 机制概念明确import 导入机制PYTHONPATH参考的全部内容,希望文章能够帮你解决py “类,模块,包与库“ 的 import 机制概念明确import 导入机制PYTHONPATH参考所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复