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

news2024/12/31 3:51:46

背景

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

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

  • 为什么要修改?

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

一、模块

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

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

import module_1
import module_2

print(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_0

print(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_0
  File "D:\my\test_py_module\module_0.py", line 1, in <module>
    import module_1
  File "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_2

print(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_2

print(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_2

print(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_2

print(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_2

print(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_2

print(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_2

print(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.coloradmin.cn/o/939561.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI智慧,书香飘溢|在图书馆的世界,知识与未来交汇!

“如果有天堂&#xff0c;天堂应该是图书馆的模样。”阿根廷国家图书馆前馆长、著名作家博尔赫斯如此形容图书馆。人类文明的演进与传承&#xff0c;倚仗于知识的积累&#xff0c;而知识的载体往往绕不开书籍&#xff0c;其集散地——图书馆&#xff0c;更是在这一过程扮演着极…

【精算研究01/10】 计量经济学的性质和范围

一、说明 计量经济学是使用统计方法来发展理论或测试经济学或金融学中的现有假设。计量经济学依赖于回归模型和零假设检验等技术。计量经济学也可以用来预测未来的经济或金融趋势。 图片来源&#xff1a;https://marketbusinessnews.com 二、 计量经济之简介 计量经济学是对经济…

javacv基础02-调用本机摄像头并预览摄像头图像画面视频

引入架包&#xff1a; <dependency><groupId>org.openpnp</groupId><artifactId>opencv</artifactId><version>4.5.5-1</version></dependency><dependency><groupId>org.bytedeco</groupId><artifactId…

【校招VIP】算法考点之堆排

考点介绍&#xff1a; 排序算法属于数据结构和算法的基础内容&#xff0c;并且也是大厂笔试中的高频考点。 堆排序是使用一棵树存储序列这个课树只保证跟节点是这棵树中的最小值&#xff0c;但并不保证其他节点是按顺序的。因此他的排序是每次从堆中取得堆顶&#xff0c;取得 n…

Qt Scroll Area控件设置,解决无法显示全部内容,且无法滚动显示问题。

前言&#xff0c;因为要显示很多条目的内容&#xff0c;原来是用Vertical Layout控件里面嵌套Horizontal layout显示了很多行控件&#xff0c;发现最简单的方法就是使用滚动条控件&#xff0c;但是无论如何调整需要滚动的控件高度&#xff0c;始终无法滚动显示内容。也就是说添…

5. 线性层及其他层

5.1 神经网络结构 5.2 线性拉平 import torch import torchvision from torch import nn from torch.nn import ReLU from torch.nn import Sigmoid from torch.utils.data import DataLoader from torch.utils.tensorboard import SummaryWriterdataset torchvision.datase…

ant-vue1.78版监听a-modal遮罩层的滚动事件

监听a-modal遮罩层的滚动事件 我们开发过程中经常有遇到监听页面滚动的事件需求&#xff0c;去做一些下拉加载或者是下拉分页的需求&#xff0c;我们直接在vue的生命周期中去绑定事件监听非常的方便&#xff0c;但如果是弹框的遮罩层的滚动监听呢&#xff1f;页面的监听完全是…

Stone Prover:StarkWare的STARK Prover

1. 引言 StarkWare将基于Apache 2.0 license&#xff0c;开源其以C编写的STARK Prover&#xff0c;名为Stone&#xff08;STARK one&#xff09;。 其基本流程为&#xff1a; 1&#xff09;编写Cairo0程序。2&#xff09;使用Cairo工具 将Cairo0程序编译为CASM。3&#xff…

数据结构:八种数据结构大全

数据结构 1.1 数据结构概述 数据结构是计算机存储、组织数据的方式&#xff1b;通常情况下&#xff0c;精心选择的数据结构可以带来更高的运行或者存储效率。数据结构的优良将直接影响着我们程序的性能&#xff1b;常用的数据结构有&#xff1a;数组&#xff08;Array&#xff…

K8S Nginx Ingress实现金丝雀发布

通过给 Ingress 资源指定 Nginx Ingress 所支持的 annotation 可实现金丝雀发布。 需给服务创建2个 Ingress&#xff0c;其中1个常规 Ingress&#xff0c;另1个为带 nginx.ingress.kubernetes.io/canary: "true" 固定的 annotation 的 Ingress&#xff0c;称为 Cana…

浅谈Lua协程和函数的尾调用

前言 虽然不经常用到协程&#xff0c;但是也不能谈虎色变。同时&#xff0c;在有些场景&#xff0c;协程会起到一种不可比拟的作用。所以&#xff0c;了解它&#xff0c;对于一些功能&#xff0c;也会有独特的思路和想法。 协程 概念 关于进程和线程的概念就不多说。 那么…

这所985专业课均分130!复试笔试很难!淘汰率很高!

一、学校及专业介绍 东南大学坐落于六朝古都南京&#xff0c;是享誉海内外的著名高等学府。学校是国家教育部直属并与江苏省共建的全国重点大学&#xff0c;是国家“双一流”、“985工程”、“211工程”重点建设高校。2017年&#xff0c;东南大学入选世界一流大学建设名单。 …

字符集(Latin1,GBK,utf8,utf8mb4)

Latin1 1个字符占一个字节GBK 1个字符占两个字节utf8utfmb3 1个字节占三个字节utf8mb4 1个字符占四个字节

OLED透明屏高清:什么是OLED透明屏?未来显示技术的巅峰之作

在现代科技快速发展的时代&#xff0c;高清显示已经成为人们对于视觉体验的基本要求。 而OLED透明屏作为一种先进的显示技术&#xff0c;以其出色的高清显示效果和透明度&#xff0c;正逐渐成为未来显示技术的巅峰之作。 一、什么是OLED透明屏 OLED透明屏采用有机发光二极管技…

Zabbix下载安装及SNMP Get使用

帮助文档&#xff1a;6. Zabbix Appliance 一、zabbix下载安装 1、获取Zabbix Appliance镜像 Download Zabbix appliance 2、使用该镜像创建虚拟机 3、打开虚拟机控制台自动安装&#xff0c;等待安装完成即可 默认配置 系统/数据库&#xff1a;root:zabbix Zabbix 前端&am…

javacv基础01-HelloWorld

JavaCV是一个针对Java编程语言的开源计算机视觉和机器学习库。它为各种流行的计算机视觉和图像处理库&#xff08;如OpenCV、FFmpeg等&#xff09;提供了Java包装&#xff0c;使Java开发人员能够在其Java应用程序中访问这些库的功能&#xff0c;无需编写本地代码。 JavaCV提供…

SpringBoot Mybatis 多数据源 MySQL+Oracle

一、背景 在SpringBoot Mybatis 项目中&#xff0c;需要连接 多个数据源&#xff0c;连接多个数据库&#xff0c;需要连接一个MySQL数据库和一个Oracle数据库 二、依赖 pom.xml <dependencies><dependency><groupId>org.springframework.boot</groupId&…

(Deep Learning)准确率和召回率的基础概念

算法模型极大的提升了对各类结果的预测效率。 【算法模型的本质】 算法模型的本质&#xff0c;是基于输入的各类变量因子&#xff0c;通过计算规则&#xff08;模型or公式&#xff09;&#xff0c;得出预测结果。 典型的预测结果比如&#xff1a; 1.&#xff08;通过历史行为…

天地图开发指南

1、 申请天地图key 1.1注册账号 注册地址&#xff1a;https://uums.tianditu.gov.cn/register 1.2 申请开发者 登录后 &#xff0c;申请开发者https://console.tianditu.gov.cn/api/register 1.3 创建应用 点击控制台&#xff0c;创建应用 1.4 天地图key 2、天地图api使用 2.…

如何开发一款飞机聊天app?即时通讯系统

随着航空业的快速发展&#xff0c;飞机旅行已经成为人们生活中常见的一部分。而在飞行期间&#xff0c;人们往往希望能够与其他乘客进行交流&#xff0c;分享旅行经历或者寻找旅途中的伴侣。为了满足这一需求&#xff0c;开发一款专门用于飞机上的聊天应用程序成为了一个有意的…