python包相关知识点之包的导入、相对路径以及绝对路径
作者:一二三四! 发布时间:2023-08-11 11:09:46
一、包
在我们的项目中,可能会有太多的模块
但是我们不能把所有的模块这样放在这里,这样项目会乱七八糟。
我们可以将所有相同类型的模块放在一个文件夹中,这个文件夹就叫做包
包就是文件夹,他用于存放文件也就是模块。包中也可以存放包
包就是一个包含了__init__.py文件的文件夹。
包只是模块的一种形式而已,包即模块。
包的结构:
包
|----__init__.py 包的标志文件
|----模块一
|----模块二
|----子包(文件夹)
|----|----__init__.py
|----|----子模块一
|----|----子模块二
二、包的导入
1.关于包相关的导入语句也分为import和from ... import ...两种,但是无论哪种,无论在什么位置,在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,否则非法。可以带有一连串的点,如demo0demo02.demo03,但都必须遵循这个原则。
2.对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。
3.对比import demo和from demo import name的应用场景:
如果我们想直接使用name那必须使用后者。
1.import 导入
在demo01_test02.py 中 导入 demo01_test01.py
demo01_test01.py 源码:
def say():
print('demo01_test01_hello')
name = '赵四'
demo01_test02.py 源码:
import base.demo01.demo01_test01
base.demo01.demo01_test01.say() # 调用test01中的say方法 输出 demo01_test01_hello
import sys
print(sys.path)
#['D:\\pycharm工作空间\\day12\\base\\demo01', 'D:\\pycharm工作空间\\day12', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\python36.zip', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\DLLs', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages\\win32', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages\\win32\\lib', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages\\Pythonwin', 'C:\\Program Files\\JetBrains\\PyCharm 2018.3.2\\helpers\\pycharm_matplotlib_backend']
2.from...import...导入
from 包名.模块名... import 变量名
使用方式: 例如 变量名() 或者print(变量名)
demo01_test02.py 源码:
from base.demo01.demo01_test01 import say
say() # demo01_test01_hello
from 包名.模块名... import 变量名1,变量名2,...
使用方式: 例如 变量名1() 或者print(变量名2)
demo01_test02.py 源码:
from base.demo01.demo01_test01 import say,name
say()
print(name) # 调用test01中的name变量
from 包名 import 模块名
使用方式:模块名.变量名() 或者 print(模块名.变量名)
demo01_test02.py 源码:
from base.demo01 import demo01_test01
demo01_test01.say() # demo01_test01_hello
from 包名 import 模块名,模块名1...
使用方式:模块名.变量名() 或者 print(模块名1.变量名)
在demo01_test02.py中调用demo02_test01.py, demo02_test02.py 源码
demo02_test01.py 源码:
def say21():
print('demo02_test01_hello')
demo02_test02.py 源码:
def say22():
print('demo02_test02_hello')
demo01_test02.py 源码:
from base.demo02 import demo02_test01,demo02_test02
demo02_test01.say21() # demo02_test01_hello
demo02_test02.say22() # demo02_test02_hello
需要注意的是from后import导入的模块,必须是明确的一个不能带点,否则会有语法错误,如:from a import b.c是错误语法
from base.demo02 import demo02_test02.say
# 报错 SyntaxError: invalid syntax
3.__init__.py文件
不管是哪种方式,只要是第一次导入包或者是包的任何其他部分,都会依次执行包下的__init__.py文件(我们可以在每个包的文件内都打印一行内容来验证一下),这个文件可以为空,但是也可以存放一些初始化包的代码。
demo1下的__init__.py文件源码:
print('啦啦啦')
demo01_test02.py 源码:
from base.demo01 import demo01_test01
demo01_test01.say()
# 啦啦啦 __init__.py中的代码执行结果
# demo01_test01_hello
4.from 包.模块 import *
此处是想从包demo02中导入所有,实际上该语句只会导入包demo02下__init__.py文件中定义的名字,我们可以在这个文件中定义__all___:
demo02下__init__.py文件的源码:
print('呜呜呜')
name = '王大夫'
demo01_test02.py 源码:
from base.demo02 import *
print(name) # 王大夫
demo02_test01.say() # 报错 无法调用
# 输出: 呜呜呜
# NameError: name 'demo02_test01' is not defined
在demo02下的__init__.py文件中加入以下源码:
print('呜呜呜')
name = '王大夫'
__all__ = ['demo02_test01','demo02_test02']
再调用:
from base.demo02 import *
demo02_test01.say21() # 成功调用
print(name) # 报错 变量name没有定义
# 呜呜呜
# demo02_test01_hello
三、包的相对和绝对导入
我们的最顶级包base是写给别人用的,然后在base包内部也会有彼此之间互相导入的需求,这时候就有绝对导入和相对导入两种方式:
绝对导入:以base作为起始
相对导入:用.或者..的方式最为起始(只能在一个包中使用,不能用于不同目录内)
1. 绝对导入
在demo01中的demo01_test02.py中调用demo02中的模块
from base.demo01 import demo01_test01
demo01_test01.say()
在 base目录下的py文件中调用demo01_test02.py
from base.demo01 import demo01_test02
demo01_test02.demo01_test01.say()
2.相对导入
在demo01中的demo01_test02.py中调用demo02中的模块
from ..demo02.demo02_test01 import say21
say21()
在 base目录下的py文件中调用demo01_test02.py
from base.demo01 import demo01_test02
demo01_test02.say21()
import sys
print(sys.path)
'''
啦啦啦
呜呜呜
demo02_test01_hello
demo02_test01_hello
['D:\\pycharm工作空间\\day12\\base', 'D:\\pycharm工作空间\\day12', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\python36.zip', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\DLLs', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages\\win32', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages\\win32\\lib', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages\\Pythonwin', 'C:\\Program Files\\JetBrains\\PyCharm 2018.3.2\\helpers\\pycharm_matplotlib_backend']
'''
相对路径运行注意事项:
在没有明确指定包结构的情况下,Python 是根据 __name__ 来决定一个模块在包中的结构的,如果是 __main__ 则它本身是顶层模块,没有包结构,如果是base.demo01.demo02 结构,那么顶层模块是 base。
如果是相对导入,一个模块必须有包结构且只能导入它的顶层模块内部的模块
如果一个模块被直接运行,则它自己为顶层模块,不存在层次结构,所以找不到其他的相对路径。
四、import 导入自定义包的子模块
特别需要注意的是:可以用import导入内置或者第三方模块(已经在sys.path中),但是要绝对避免使用import来导入自定义包的子模块(没有在sys.path中),应该使用from... import ...的绝对或者相对导入。
demo03中的test01源码:
def test():
print('这是一个测试方法')
直接运行demo03_test02模块
import test01
test01.test()
import sys
print(sys.path)
'''这是一个测试方法
['D:\\pycharm工作空间\\day12\\base\\demo03', 'D:\\pycharm工作空间\\day12', 'D:\\pycharm工作空间\\day12\\base\\demo03', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\python36.zip', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\DLLs', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages\\win32', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages\\win32\\lib', 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages\\Pythonwin', 'C:\\Program Files\\JetBrains\\PyCharm 2018.3.2\\helpers\\pycharm_matplotlib_backend']
'''
不会报错因为sys.path中已经添加了day05-包/demo03路径。Import会从sys.path中依次搜索路径。
在base目录下导入demo03_test02.py进行使用
from base.demo03 import test02
# 报错 ModuleNotFoundError: No module named 'test01'
因为此时的sys.path中只有demo01-包.py的路径 .../day05-包,import demo03_test01 只能从/day05-包下查找 demo03_test01模块。找不到因此报错。
解决import 导入包时的报错问题
我们可以在sys.path中添加import搜索的路径。
import sys,os
path = os.path.abspath(__file__)
print(path)
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
print(BASE_DIR)
sys.path.append(BASE_DIR)
print(sys.path)
import base.demo03.test01
base.demo03.test01.test() # 这是一个测试方法
五、包的单独导入
单独导入包名称时不会导入包中所有包含的所有子模块
import base.demo03
base.demo03.test01.test()
# 报错 AttributeError: module 'base.demo03' has no attribute 'test01'
解决办法:需要从__init__.py中进行初始化操作
进行上诉操作后:
六、包的安装和发布
1、在包的同级目录创建 setup.py
from distutils.core import setup
setup(name='bag',
version='1.0,3',
description='描述:这是我的第一个包',
author='zxb',
author_email='505555162@qq.com',
py_modules=['test1', 'test2'],
)
2.在命令行 运行 python setup.py build (可以不执行 )
构建模块
4.生成发布的压缩包 运行 python setup.py sdist
5、安装包
导入自己的包进行测试
测试成功!!
包的卸载: 直接找到对应的位置删除即可。
来源:https://blog.csdn.net/weixin_42223833/article/details/86168012


猜你喜欢
- 在编写JavaScript程序时往往需要检测某一变量是否存在,这是一件非常简单的工作,但如果不细心也会遇到一些问题。主要有一些几点: 1、普
- 特征降维0维 标量1维 向量2维 矩阵概念降维是指在某些限定条件下,降低随机变量(特征)个数,得到一组“不相关&
- 本文实例讲述了PHP global全局变量的使用与注意事项。分享给大家供大家参考,具体如下:使用global在方法里面声明外部变量为全局变量
- 如下所示:'''Created on 2018-4-20例子:每天凌晨3点执行func方法''
- 在使用javascript编程时浏览器中经常会遇到的两个麻烦,下面提供两个函数解决方式做参考,并提供一个demo让你更直观地了解我所说的这两
- 一个3层嵌套列表mm=["a",["b","c",["inner&qu
- 首先是准备工作Python 2.7.11:下载pythonPycharm:下载Pycharm其中python2和python3目前同步发行,
- 进行已经矢量化后的字符串数据,可以使用pandas的Series数据对象的map方法。这样,对于未经矢量化的数据也可以先进行数据的矢量化转换
- 引言:以前写的一个批量xls转csv的python简单脚本,用的是python2.7#coding=utf-8import osimport
- 概述从今天开始, 小白我将带领大家一起来补充一下 数据库的知识.自连接自连接 (Self Join) 是一种特殊的表连接. 自连接指相互连接
- Jones向量假设光波沿z轴传播,那么其三个方向的电场分量可以表示为Jones矩阵能够保证二维列向量形状不变的运算有无穷多种,但最符合我们直
- 图像处理工具——灰度直方图灰度直方图时图像灰度级的函数,用来描述每个灰度级在图像矩阵中的像素个数或者占有率。例子:矩阵图片来自网络,侵删!上
- Python全局锁(1)全局锁导致的问题全局锁的英文简称是GIL,全称是Global Interpreter Lock(全局解释器锁),来源
- 前提对Vue全家桶有基本的认知.用有node环境了解express另外本篇只是介绍登录状态的权限验证,以及登录,注销的前后端交互.具体流程(
- 马上就是圣诞节了,先提前祝大家圣诞快乐!:christmas_tree::christmas_tree::christmas_t
- 首先要导入JDBC的jar包;接下来,代码:Class.forName(xxx.xx.xx)返回的是一个类Class.forName(xxx
- 每次在操作数据库的时候最烦的就是根据表单提交的内容写sql语句,特别是字段比较多的时候很麻烦,动不动就容易写错。所以我就写了下面的生成sql
- 常规通过迭代或set方法,都无法保证去重后的顺序问题如下,我们可以通过列表的索引功能,对set结果进行序列化old_list=["
- 学用python也有3个多月了,用得最多的还是各类爬虫脚本:写过抓代理本机验证的脚本,写过在discuz论坛中自动登录自动发贴的脚本,写过自
- 数组的定义:方法1.var mycars=new Array()mycars[0]="Saab"mycars[1]=&q