import问题:https://zhuanlan.zhihu.com/p/69099185
一、sys模块
sys模块是python自带模块,包含了与Python解释器和它的环境有关的函数。利用 import 语句输入sys 模块。
dir(sys):通过dir()方法查看模块中可用的方
1. sys.path
sys.path:包含了Python解释器自动查找所需模块的路径的列表。
在Python启动时,sys.path根据内建规则和PYTHONPATH变量进行初始化。可以进行append、insert、pop、remove等各种列表相关的操作,但通常都进行append操作,在PYTHONPATH环境变量中增加相应的路径。sys.path.append("自定义模块路径"),这种方法是运行时修改,脚本运行后就会失效的。
sys.path列表里的路径分为三种:
- 当前执行脚本(主动执行,而不是被其他模块调用)所在路径。是列表中的第一个元素,若没有执行脚本,则是个空字符串。
- 第二种是python内置的标准库路径,PYTHONPATH。
- 其他的是安装的第三方模块路径。
python import某个A模块时,首先会从python的内置模块中查找,是否含有该模块的定义。若未查询到,然后会从sys.path对应的模块路径查询,是否含有对应模块的定义,如果搜索完成依然没有对应A模块时,则抛出import的异常。
2. sys.argv
sys.argv获取命令行参数, 返回值是List,列表的第一个元素是脚本名称,第二个元素开始才是真正的参数。文件test.py,内容如下:
import sys
print(sys.argv)
在命令行中运行:python3 test.py 33,输出如下:
['test.py', '33']
二、导入自定义包:
在实际开发中,默认包含了当前目录为搜索路径,所以,当前目录下的模块和子模块均可以正常访问。一个模块只会被导入一次,不管你执行了多少次import。这样可以防止导入模块被一遍又一遍地执行。
但是若一个模块需要import平级的不同目录的模块,或者上级目录里面的模块,就可以通过修改path来实现,方法有以下几种:
1. 临时添加模块完整路径
使用sys.path.append(path)添加相关的路径,通过该方法添加的目录,只能在执行当前文件的窗口中有效,窗口关闭后即失效。个人比较推荐这种方法,比较干净,避免一些冲突问题。
比如现在的代码目录结构:
/src/configs/config.py
/src/common/Database.py
假如Database.py期望导入config.py,则可以增加上级目录到sys.path列表里面:
parent_path = os.path.dirname(sys.path[0]) 去掉文件名,返回目录
if parent_path not in sys.path:
sys.path.append(parent_path)
import configs.config
最好加个判断,避免重复加入。也可以使用下面的代码:
import sys
sys.path.append(‘../’) # 动态添加a_package文件夹的所在路径
2. 将模块保存到指定位置
对 Python 本身进行扩展的模块,应该直接安装在 Python 内部以便被所有程序共享,此时就可借助于 Python 默认的模块加载路径(保存在 sys.path 变量中)。
通常来说,默认将 Python 的扩展模块添加在libsite-packages路径下,它专门用于存放Python的扩展模块和包。
3. 设置环境变量
使用PYTHONPATH环境变量,在这个环境变量中输入相关的路径,不同的路径之间用逗号(英文的!)分开。
如果PYTHONPATH 变量不存在,可以创建它!路径会自动加入到sys.path中,而且可以在不同的python版本中共享,应该是一样较为方便的方法。
4. 增加.pth文件,推荐!
在site-packages下新建.pth文件(用于添加额外的sys.path),将模块的绝对路径写进去,一行一个路径。解释器启动时,.pth文件里列举出来的存在于文件系统的目录将被添加到sys.path。如果它被添加到系统级的Python解释器,安装一个.pth文件可能需要管理员权限。
这个不失为一个好的方法,但存在管理上的问题,而且不能在不同的python版本中共享。
三、绝对路径和相对路径导包的区别:
1. 绝对路径导包:
从当前执行脚本所在路径中导入需要的module。
2. 相对路径导包:
单点表示引用的模块或包,与当前模块在同一目录中(同一个包中)。
两点表示引用的模块,在当前模块所在位置的父目录中。
相对导入只适用于顶级包之内的模块,用了相对导入的模块文件不能作为顶层执行文件。