一步一步实验,讲解python中模块和包的使用

背景

  • 为什么要提出这个问题?

在一个项目中,每一个python文件打开后,都会看到依赖了其他的一些包、模块等;概念混乱,魔改目标不清晰

  • 为什么要修改?

如果需要将某开源包进行自定义处理,不再使用pip install xxx的方式来使用,那么就需要将项目代码放在自己的项目中,通过自己的脚本去调用

一、模块

首先,python没有确定的项目入口,原则上每一个文件都可以是入口,每一个文件入口进去后,所执行的代码也不一定相同,但一般还是以main.py的约定俗成来规定项目入口;那么来看例子,目前有多个文件:

这张图的意思就是,每一个python文件本质都是一个模块。
module_0.py代码如下:

import module_1
import module_2print(module_1.module_name)
print(module_2.module_name)
module_1.module_info()
module_2.module_info()

module_1.py代码如下:

module_name = 'module1'def module_info():print("func in module1")

module_2.py代码如下:

module_name = 'module2'def module_info():print("func in module2")

执行module_0.py,有几种情况:

  1. 点击IDE的运行,或者vscode装了插件后的运行的按钮,实际上是调用了
& C:/msys64/mingw64/bin/python.exe d:/my/test_py_module/module_0.py

这个命令行

  1. 直接命令行执行:
python .\module_0.py

其实本质是一样的,因为环境变量添加了python,所以可以识别,并且依旧调用了自己的某个python解释器(有多个解释器的时候需要在IDE选择,或者使用完整路径指定解释器)

有时候会看到py文件中有以下内容,例如在module_0.py中加入:

if __name__ == "__main__":print("hello world")

再执行,发现:

module1
module2
func in module1
func in module2
hello world

多了其作为程序入口(即main的角色)时需要进行的步骤

那么让module_1.py作为主函数呢?

修改其代码,试图让其引用module_0.py

module_name = 'module1'def module_info():print("func in module1")import module_0print(module_0.module_name)
module_0.module_info()

发现出错:

(base) PS D:\my\test_py_module> python .\module_1.py
Traceback (most recent call last):File "D:\my\test_py_module\module_1.py", line 6, in <module>import module_0File "D:\my\test_py_module\module_0.py", line 1, in <module>import module_1File "D:\my\test_py_module\module_1.py", line 8, in <module>print(module_0.module_name)^^^^^^^^^^^^^^^^^^^^
AttributeError: partially initialized module 'module_0' has no attribute 'module_name' (most likely due to a circular import)

可以发现模块不可以循环引用,正常来讲一个主函数引用其他模块是一种更合适的方式

最后说一句,模块的引用路径顺序:

  1. 当前目录:Python解释器会先搜索当前目录,也就是包含当前脚本的目录
  2. 环境变量PYTHONPATH指定的目录:如果PYTHONPATH环境变量被设置了,Python解释器会搜索这些目录。
  3. Python默认的安装路径:Python解释器会搜索Python默认的安装路径下的标准库目录和第三方库目录。

三、包

包的出现就是为了避免模块太多放在同一级目录下带来的繁琐问题:

  • 不同模块中可以出现同名的变量、函数等,模块名不同,就可以区分
  • 模块太多之后,模块也容易重名,就需要再套一级

所以直接看例子,当前目录结构:

各包的内容:

'''package_1''''''module_1'''
module_name = 'module1'def module_info():print("func in module1")'''module_2'''
module_name = 'module2'def module_info():print("func in module2")
'''package_2''''''module_1'''
module_name = 'module1 from package_2'def module_info():print("func in module1 from package_2")'''module_2'''
module_name = 'module2 from package_2'def module_info():print("func in module2 from package_2")

module_0.py入口函数:

import package_1.module_1 as module_1
import package_1.module_2 as module_2print(module_1.module_name)
print(module_2.module_name)
module_1.module_info()
module_2.module_info()import package_2.module_1
import package_2.module_2print(package_2.module_1.module_name)
print(package_2.module_2.module_name)
package_2.module_1.module_info()
package_2.module_2.module_info()if __name__ == "__main__":print("hello world")

结果:

module1
module2
func in module1
func in module2
module1 from package_2
module2 from package_2
func in module1 from package_2
func in module2 from package_2
hello world

注意:import 参数的最后部分必须是模块名(文件名),而不能是包名(目录名)

可以发现,我们在这里并没有像一些规范的代码一样,严格的加入__init__.py文件,这个文件是一个 Python 包的标识文件,它告诉 Python 解释器该目录应该被视为一个包。当一个包被导入时,Python 解释器会首先查找并执行该包下的 __init__.py 文件,然后才会继续执行其他模块。

__init__.py 文件可以为空,也可以包含 Python 代码,用于初始化包的状态或执行其他必要的操作。例如,它可以定义包级别的变量、函数或类,或者导入其他模块或子包。

在 Python 3.3 及以上版本中,__init__.py 文件不再是必需的,因为 Python 解释器可以自动识别包目录。但是,为了保持向后兼容性,建议在包目录中始终包含一个空的 __init__.py 文件。

所以可以加一下:

如果更多级别的目录,如图所示:

那么在主函数(module_0.py)中引用子包中的模块,并不是难事,直接使用:

import package_1.module_1 as module_1
import package_1.module_2 as module_2print(module_1.module_name)
print(module_2.module_name)
module_1.module_info()
module_2.module_info()import package_2.module_1
import package_2.module_2print(package_2.module_1.module_name)
print(package_2.module_2.module_name)
package_2.module_1.module_info()
package_2.module_2.module_info()import package_1.sub_package_1.module_1 as psm_1
import package_1.sub_package_1.module_2 as psm_2print(psm_1.module_name)
print(psm_2.module_name)
psm_1.module_info()
psm_2.module_info()if __name__ == "__main__":print("hello world")

输出:

module1
module2
func in module1
func in module2
module1 from package_2
module2 from package_2
func in module1 from package_2
func in module2 from package_2
module1 from sub_package_1
module2 from sub_package_1
func in module1 from sub_package_1
func in module2 from sub_package_1
hello world

有时候需要在package_2中,使用子包的模块,就在package_2试一下,引入包1的模块,再引入包1中子包的模块:

主函数使用:

import package_1.module_1 as module_1
import package_1.module_2 as module_2print(module_1.module_name)
print(module_2.module_name)
module_1.module_info()
module_2.module_info()import package_2.module_1
import package_2.module_2print(package_2.module_1.module_name)
print(package_2.module_2.module_name)
package_2.module_1.module_info()
package_2.module_2.module_info()package_2.module_1.import_sub()
package_2.module_2.import_sub()if __name__ == "__main__":print("hello world")

结果:

module1
module2
func in module1
func in module2
module1 from package_2
module2 from package_2
func in module1 from package_2
func in module2 from package_2
module1 from sub_package_1
successfully import sub_package
module1
successfully import package_1
hello world

有了这样的关系,更复杂的包结构也可以分析了

四、直接导入类和函数

有时候可以看到导入模块后,使用时需要先加模块名,再加类名或者函数名,但如果只使用了模块中特定的类或者函数,为了方便可以直接导入到具体的类或者函数:

在Python中,可以使用import语句来导入类和函数。如果要导入一个模块中的所有内容,可以使用*通配符。

例如,假设我们有一个名为my_module的模块,其中包含一个名为MyClass的类和一个名为my_function的函数。要导入这些内容,可以使用以下语法:

from my_module import MyClass, my_function

这将使MyClassmy_function在当前作用域中可用。如果要导入所有内容,可以使用以下语法:

from my_module import *

这将导入my_module中的所有内容,并使其在当前作用域中可用。但是,这种方法不是推荐的做法,因为它可能会导致命名冲突和代码可读性问题。

五、遗留问题

  1. __init__.py执行的关系,具体使用方法
  2. 导入模块的具体类,但没有导入模块名,此类依赖了本身模块中的其他东西,怎么处理这样的关系:

当你执行from my_module import MyClass时,Python会尝试导入my_module模块,并查找MyClass类。如果MyClass类依赖于my_module中的其他类,那么这些类也会被导入。

具体来说,当Python导入一个模块时,它会执行该模块的代码。如果该模块依赖于其他模块,那么Python会尝试导入这些模块。如果这些模块也依赖于其他模块,那么Python会递归地导入这些模块,直到所有依赖关系都被满足为止。

在导入模块时,Python会将已导入的模块缓存起来,以便在后续的导入中重用。这样可以避免重复导入模块,提高导入效率。

六、参考资料

  • https://pythonhowto.readthedocs.io/zh_CN/latest/module.html#
  • ChatGPT
  • python官方文档:https://docs.python.org/zh-cn/3/reference/import.html

七、相对导入和绝对导入

在Python中,导入模块有两种方式:相对导入和绝对导入。

相对导入是相对于当前模块的位置进行导入,使用相对路径来指定要导入的模块。相对导入使用点号(.)来表示当前模块,使用双点号(…)来表示当前模块的父模块。相对导入的语法如下:

from .module import name
from ..module import name

绝对导入是从项目的根目录开始导入模块,使用绝对路径来指定要导入的模块。绝对导入使用包的完整名称来指定要导入的模块。绝对导入的语法如下:

from package.module import name

在Python 3中,相对导入和绝对导入的默认行为是不同的。在Python 3中,相对导入默认是相对于当前模块的位置进行导入,而绝对导入默认是从项目的根目录开始导入模块。如果要使用Python 2中的相对导入行为,可以在模块中添加以下代码:

from __future__ import absolute_import

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/109137.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python 包管理(pip、conda)基本使用指南

Python 包管理 概述 介绍 Python 有丰富的开源的第三方库和包&#xff0c;可以帮助完成各种任务&#xff0c;扩展 Python 的功能&#xff0c;例如 NumPy 用于科学计算&#xff0c;Pandas 用于数据处理&#xff0c;Matplotlib 用于绘图等。在开始编写 Pytlhon 程序之前&#…

数据隐私与安全在大数据时代的挑战与应对

文章目录 数据隐私的挑战数据安全的挑战应对策略和方法1. 合规和监管2. 加密技术3. 匿名化和脱敏4. 安全意识培训5. 隐私保护技术 结论 &#x1f388;个人主页&#xff1a;程序员 小侯 &#x1f390;CSDN新晋作者 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 ✨收录专栏&…

【算法与数据结构】513、LeetCode找树左下角的值

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;这道题用层序遍历来做比较简单&#xff0c;最底层最左边节点就是层序遍历当中最底层元素容器的第一个值…

vue 简单实验 自定义组件 独立模块

1.概要 2.代码 2.1 const Counter {data() {return {counter: 0}},template:<div>Counter: {{ counter }}</div> }export default Counter 2.2 import Counter from ./t2.jsconst app Vue.createApp({components: {component-a: Counter} })app.mount(#count…

浅析 GlusterFS 与 JuiceFS 的架构异同

在进行分布式文件存储解决方案的选型时&#xff0c;GlusterFS 无疑是一个不可忽视的考虑对象。作为一款开源的软件定义分布式存储解决方案&#xff0c;GlusterFS 能够在单个集群中支持高达 PiB 级别的数据存储。自从首次发布以来&#xff0c;已经有超过十年的发展历程。目前&am…

不使用ip和port如何进行网络通讯(raw socket应用例子)

主要应用方向是上位机和嵌软(如stm32单片机)通讯&#xff0c;不在单片机中嵌入web server&#xff0c;即mac层通讯。 一、下面先了解网络数据包组成。 常见数据包的包头长度: EtherHeader Length: 14 BytesTCP Header Length : 20 BytesUDP Header Length : 8 BytesIP Heade…

Spring@Scheduled定时任务接入XXL-JOB的一种方案(基于SC Gateway)

背景 目前在职的公司&#xff0c;维护着Spring Cloud分布式微服务项目有25个。其中有10个左右微服务都写有定时任务逻辑&#xff0c;采用Spring Scheduled这种方式。 Spring Scheduled定时任务的缺点&#xff1a; 不支持集群&#xff1a;为避免重复执行&#xff0c;需引入分…

【VMware】CentOS 设置静态IP(Windows 宿主机)

文章目录 1. 更改网络适配器设置2. 配置虚拟网络编辑器3. 修改 CentOS 网络配置文件4. ping 测试结果 宿主机&#xff1a;Win11 22H2 虚拟机&#xff1a;CentOS-Stream-9-20230612.0 (Minimal) 1. 更改网络适配器设置 Win R&#xff1a;control 打开控制面板 依次点击&#x…

【应用层】网络基础 -- HTTPS协议

HTTPS 协议原理加密为什么要加密常见的加密方式对称加密非对称加密 数据摘要&&数据指纹 HTTPS 的工作过程探究方案1-只使用对称加密方案2-只使用非对称加密方案3-双方都使用非对称加密方案4-非对称加密对称加密中间人攻击-针对上面的场景 CA认证理解数据签名方案5-非对…

15-模型 - 一对多 多对多

一对多&#xff1a; 1. 在多的表里定义外键 db.ForeignKey(主键) 2. 增加字段 db.relationship 建立联系 ("关联表类名","反向引用名") from ext import db# 一 class User(db.Model):id db.Column(db.Integer, primary_keyTrue, autoincrementTrue)us…

Dart PowerTCP Emulation for .NET Crack

Dart PowerTCP Emulation for .NET Crack .NET CF上的PowerTCP Emulation为手持设备提供了高级的Internet通信组件。这些功能允许同步操作&#xff0c;这样可以消耗更少的资源&#xff0c;提供更大的灵活性&#xff0c;并生成易于维护的软件。带有.NET的PowerTCP仿真包括VT52、…

gpt-3.5-turbo微调图形界面;Hugging Face完成2.35亿美元融资

&#x1f989; AI新闻 &#x1f680; 人工智能初创公司Hugging Face完成2.35亿美元融资&#xff0c;估值达到45亿美元 摘要&#xff1a;总部位于纽约的人工智能初创公司Hugging Face完成了一轮2.35亿美元的融资&#xff0c;估值达到45亿美元。本轮融资的投资者包括谷歌、亚马…

几个nlp的小任务(多选问答)

@TOC 安装库 多选问答介绍 定义参数、导入加载函数 缓存数据集 随机选择一些数据展示 进行数据预处理部分(tokenizer) 调用t

Android全面屏下,默认不会全屏显示,屏幕底部会留黑问题

前些天发现了一个蛮有意思的人工智能学习网站,8个字形容一下"通俗易懂&#xff0c;风趣幽默"&#xff0c;感觉非常有意思,忍不住分享一下给大家。 &#x1f449;点击跳转到教程 公司以前的老项目&#xff0c;便出现了这种情况&#xff0c;网上搜索了各种资料&#xf…

Web Components详解-Custom Elements

目录 引言 演变过程 概述 使用方式 创建标签 定义标签 使用标签 获取标签 异步定义标签 升级标签 完整案例 结语 相关代码 参考文章 引言 随着项目体量的增大&#xff0c;组件化和模块化的优势也愈发明显了&#xff0c;构建可重复使用、独立、可互操作的组件变得…

【Java基础】Java注解与反射

文章目录 ⭐️写在前面的话⭐️1、什么是注解&#xff1f;注解的分类常用的Java注解 2、元注解TargetRetentionDocumentedInherited 3、自定义注解Override注解的基本格式 4、什么是反射&#xff1f;什么时候需要用到反射&#xff1f;反射的应用场合 5、反射的原理6、反射机制的…

基于AVR128单片机智能传送装置

一、系统方案 1、板载可变电阻&#xff08;电位器&#xff09;R29的电压作为处理器ATmega128的模数转换模块中单端ADC0的模拟信号输入&#xff08;跳线JP13短接&#xff09;。 2、调节电位器&#xff0c;将改变AD转换接口ADC0的模拟信号输入&#xff0c;由处理器完成ADC0的A/D转…

生态经济学领域里的R语言机器学(数据的收集与清洗、综合建模评价、数据的分析与可视化、数据的空间效应、因果推断等)

近年来&#xff0c;人工智能领域已经取得突破性进展&#xff0c;对经济社会各个领域都产生了重大影响&#xff0c;结合了统计学、数据科学和计算机科学的机器学习是人工智能的主流方向之一&#xff0c;目前也在飞快的融入计量经济学研究。表面上机器学习通常使用大数据&#xf…

光谱成像系统视觉均匀校准积分球光源

数字相机的光谱灵敏度是成像传感器、光学透镜、滤光片以及相机内部图像处理过程等诸多因素的综合结果。即使是同一台相机&#xff0c;采用不同的光学镜头和不同的滤光片&#xff0c;由于光学系统的结构和光学材料的透过率不同&#xff0c;导致整个成像系统的光谱灵敏度也有所差…

计算机竞赛 基于机器视觉的二维码识别检测 - opencv 二维码 识别检测 机器视觉

文章目录 0 简介1 二维码检测2 算法实现流程3 特征提取4 特征分类5 后处理6 代码实现5 最后 0 简介 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于机器学习的二维码识别检测 - opencv 二维码 识别检测 机器视觉 该项目较为新颖&#xff0c;适合作为竞赛课…