成都Python周末班:Python中的绝对导入和相对导入
off999 2024-09-18 22:38 29 浏览 0 评论
如果你做过有多个文件的Python项目,那么你一定用过import语句。
即使是对于有多个项目的Python支持者来说,import也会让人困惑!你可能正阅读本文,因为希望更深入地了解Python中的导入,尤其是绝对和相对导入。在本教程中,你将了解两者之间的差异,以及它们的利弊。我们立即开始吧!
关于Import的快速回顾
你需要对Python模块和包有一个很好的理解,以了解导入的工作方式。Python模块是一个扩展名是.py的文件,Python包是其中包含模块的任何文件夹(或者,在Python 2中,是至少包含一个__init__.py文件的文件夹)。
当一个模块中的代码需要访问另一个模块或包中的代码时,会发生什么情况?导入它!
Import如何工作
但import究竟是如何工作的呢?假设你导入一个模块abc,就像这样:
Python要做的第一件事是查找sys.modules中的abc名称。这是预先导入的所有模块的缓存。
如果在模块缓存中没有找到该名称,Python将通过内置模块列表进行搜索。这些模块是和Python一起预先安装的,并且可以在Python标准库中找到。如果在内置模块中仍没有找到该名称,那么Python在sys.path定义的目录列表中搜索它。此列表通常包括当前目录,首先搜索该目录。
当Python找到该模块时,将它绑定到本地作用域中的名称。这意味着现在定义了abc,而且可以在当前文件中使用,而不引发NameError。
如果找不到该名字,会得到ModuleNotFoundError。你可以在Python文档找到更多关于导入的信息!
注意:安全问题
请注意,Python的导入系统会带来一些重大的安全风险。这主要是由于其灵活性。例如,模块缓存是可写的,并且有可能使用导入系统重写Python核心功能。从第三方软件包导入也可能给应用程序带来安全威胁。
导入语句语法
既然你知道导入语句是如何工作的,让我们来探究它们的语法。你可以导入包和模块。(注意,导入一个包基本上是导入包的__init__.py文件作为模块。)还可以从包或模块中导入特定的对象。
一般有两种类型的导入语法。当使用第一种时,直接导入资源,如下所示:
abc可以是一个包或一个模块。
当使用第二种语法时,从另一个包或模块导入资源。下面是一个例子:
xyz可以是模块、子包或对象,例如类或函数。你还可以重命名导入的资源,如:
这在脚本内将导入的资源abc重命名为other_name。它现在必须被引用为other_name,否则它将不被识别。
导入语句的风格
Python的官方风格指南——PEP 8,在编写导入语句时有几个忠告。总结如下:
1. 导入总是位于文件的顶部,在任何模块注释和文档字符串之后。
2. 导入应该根据导入情况来划分。通常有三类:
标准库导入(Python的内置模块)
相关第三方导入(已安装且不属于当前应用程序的模块)
本地应用程序导入(属于当前应用程序的模块)
3. 每一组导入应该被空行隔开。
在每个导入组中按字母顺序排列导入也是一个好主意。这使得查找特定的导入更加容易,尤其是当文件中有许多导入时。
下面是如何设计导入语句的示例:
上面的导入语句被划分为三个不同的组,由空行分隔。它们也按字母顺序排列在每组中。
绝对导入
你已经掌握了如何编写import语句以及如何像专业人士那样设置样式。现在是时候了解更多关于绝对导入的信息了。绝对导入从项目根文件夹中使用其完整路径导入指定的资源。
语法与实例
假设你有以下目录结构:
有一个project目录,包含两个子目录,package1和package2。package1目录有两个文件,module1.py和module2.py。
package2目录有三个文件:两个模块:module3.py和module4.py,以及初始化文件__init__.py。它还包含一个目录subpackage1,subpackage1又包含一个文件module5.py。
假设如下:
1.package1/module2.py包含一个函数function1。
2.package2/__init__.py包含一个类class1.
3.package2/subpackage1/module5.py包含一个函数function2.
以下是绝对导入的实际例子:
请注意,必须从顶级包文件夹中为每个包或文件提供详细路径。这有点类似于它的文件路径,但是我们使用点(.)代替斜杠(/)。
绝对导入的利弊
绝对导入是首选,因为它们非常明确和直接。仅仅通过查看语句就可以很容易地确定导入资源的位置。此外,即使导入语句的当前位置发生更改,绝对导入仍然有效。事实上,PEP 8明确建议绝对导入。
然而,有时,绝对导入会变得相当冗长,这取决于目录结构的复杂性。想象一下有这样的语句:from package1.subpackage2.subpackage3.subpackage4.module5 import function6 那太荒谬了,对吧?幸运的是,在这种情况下,相对导入是一个很好的选择!
相对导入
相对导入指定资源相对于当前位置导入,即导入语句所在的位置。相对导入有两种类型:隐式和显式。隐式相对导入在Python 3中已经被弃用,所以我不会在这里涉及它们。
语法与实例
相对导入的语法取决于当前位置以及要导入的模块、包或对象的位置。下面是一些相对导入的例子:
你可以看到上面每个导入语句中至少有一个点。相对导入使用点标记来指定位置。
一个点意味着引用的模块或包位于与当前位置相同的目录中。两个点意味着它在当前位置的父目录中,也就是上层的目录。三个点意味着它在祖父母目录中,等等。如果你使用类似UNIX的操作系统,可能对此很熟悉!
假设你拥有与以前相同的目录结构:
回忆文件内容:
1.package1/module2.py包含一个函数function1。
2.package2/__init__.py包含一个类class1.
3.package2/subpackage1/module5.py包含一个函数function2.
你可以通过这种方式将function1导入package1/module1.py中:
这里只使用一个点,因为module2.py位于与当前模块相同的目录中,当前模块是module1.py。
你可以将class1 和function2 以这种方式导入package2/module3.py文件中:
在第一个导入语句中,一个点表示你正在从当前包导入class1。别忘了,导入一个包基本上是导入包的__init__.py文件作为模块。在第二个导入语句中,你将再次使用一个点,因为subpackage1 与当前模块module3.py位于同一个目录中。
相对导入的利弊
相对导入的一个明显优势是它们相当简练。根据当前位置,它们可以将你之前看到的冗长的可笑的导入语句转换为如下简单的语句:
不幸的是,相对导入可能是混乱的,特别是对于目录结构可能改变的共享项目。相对导入也不像绝对导入一样可读,而且很难识别导入资源的位置。
结尾
来到绝对和相对导入速成课程的结尾,很好!现在,你熟悉了导入的工作原理。你已经学习了编写导入语句的最佳实践,并且你知道绝对导入和相对导入之间的区别。
有了新的技能,你可以自信地从Python标准库、第三方包和自己的本地包导入包和模块。记住,你通常应该选择绝对导入,而不是相对导入,除非路径是复杂的,并且会使声明太长。
成都达内小编注:
相对引用不仅仅是为了缩短引用路径的长度,更多的是用于编写库(很多项目共用的软件包)时使用。在库软件包中,库代码往往不知道自己会被用于何处、绝对路径是什么,只有使用相对引用,库软件包才能方便地被使用于各种不同的项目。
相关推荐
- Linux 网络协议栈_linux网络协议栈
-
前言;更多学习资料(包含视频、技术学习路线图谱、文档等)后台私信《资料》免费领取技术点包含了C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,Z...
- 揭秘 BPF map 前生今世_bpfdm
-
1.前言众所周知,map可用于内核BPF程序和用户应用程序之间实现双向的数据交换,为BPF技术中的重要基础数据结构。在BPF程序中可以通过声明structbpf_map_def...
- 教你简单 提取fmpeg 视频,音频,字幕 方法
-
ffmpeg提取视频,音频,字幕方法(HowtoExtractVideo,Audio,SubtitlefromOriginalVideo?)1.提取视频(ExtractVi...
- Linux内核原理到代码详解《内核视频教程》
-
Linux内核原理-进程入门进程进程不仅仅是一段可执行程序的代码,通常进程还包括其他资源,比如打开的文件,挂起的信号,内核内部的数据结构,处理器状态,内存地址空间,或多个执行线程,存放全局变量的数据段...
- Linux C Socket UDP编程详解及实例分享
-
1、UDP网络编程主要流程UDP协议的程序设计框架,客户端和服务器之间的差别在于服务器必须使用bind()函数来绑定侦听的本地UDP端口,而客户端则可以不进行绑定,直接发送到服务器地址的某个端口地址。...
- libevent源码分析之bufferevent使用详解
-
libevent的bufferevent在event的基础上自己维护了一个buffer,这样的话,就不需要再自己管理一个buffer了。先看看structbufferevent这个结构体struct...
- 一次解决Linux内核内存泄漏实战全过程
-
什么是内存泄漏:程序向系统申请内存,使用完不需要之后,不释放内存还给系统回收,造成申请的内存被浪费.发现系统中内存使用量随着时间的流逝,消耗的越来越多,例如下图所示:接下来的排查思路是:1.监控系统中...
- 彻底搞清楚内存泄漏的原因,如何避免内存泄漏,如何定位内存泄漏
-
作为C/C++开发人员,内存泄漏是最容易遇到的问题之一,这是由C/C++语言的特性引起的。C/C++语言与其他语言不同,需要开发者去申请和释放内存,即需要开发者去管理内存,如果内存使用不当,就容易造成...
- linux网络编程常见API详解_linux网络编程视频教程
-
Linux网络编程API函数初步剖析今天我们来分析一下前几篇博文中提到的网络编程中几个核心的API,探究一下当我们调用每个API时,内核中具体做了哪些准备和初始化工作。1、socket(family...
- Linux下C++访问web—使用libcurl库调用http接口发送解析json数据
-
一、背景这两天由于一些原因研究了研究如何在客户端C++代码中调用web服务端接口,需要访问url,并传入json数据,拿到返回值,并解析。 现在的情形是远程服务端的接口参数和返回类型都是json的字符...
- 平衡感知调节:“系统如人” 视角下的架构设计与业务稳定之道
-
在今天这个到处都是数字化的时代,系统可不是一堆冷冰冰的代码。它就像一个活生生的“数字人”,没了它,业务根本转不起来。总说“技术要为业务服务”,但实际操作起来问题不少:系统怎么才能快速响应业务需求?...
- 谈谈分布式文件系统下的本地缓存_什么是分布式文件存储
-
在分布式文件系统中,为了提高系统的性能,常常会引入不同类型的缓存存储系统(算法优化所带来的的效果可能远远不如缓存带来的优化效果)。在软件中缓存存储系统一般可分为了两类:一、分布式缓存,例如:Memca...
- 进程间通信之信号量semaphore--linux内核剖析
-
什么是信号量信号量的使用主要是用来保护共享资源,使得资源在一个时刻只有一个进程(线程)所拥有。信号量的值为正的时候,说明它空闲。所测试的线程可以锁定而使用它。若为0,说明它被占用,测试的线程要进入睡眠...
- Qt编写推流程序/支持webrtc265/从此不用再转码/打开新世界的大门
-
一、前言在推流领域,尤其是监控行业,现在主流设备基本上都是265格式的视频流,想要在网页上直接显示监控流,之前的方案是,要么转成hls,要么魔改支持265格式的flv,要么265转成264,如果要追求...
- 30 分钟搞定 SpringBoot 视频推拉流!实战避坑指南
-
30分钟搞定SpringBoot视频推拉流!实战避坑指南在音视频开发领域,SpringBoot凭借其快速开发特性,成为很多开发者实现视频推拉流功能的首选框架。但实际开发中,从环境搭建到流处理优...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- python计时 (73)
- python安装路径 (56)
- python类型转换 (93)
- python进度条 (67)
- python吧 (67)
- python的for循环 (65)
- python格式化字符串 (61)
- python静态方法 (57)
- python列表切片 (59)
- python面向对象编程 (60)
- python 代码加密 (65)
- python串口编程 (77)
- python封装 (57)
- python写入txt (66)
- python读取文件夹下所有文件 (59)
- python操作mysql数据库 (66)
- python获取列表的长度 (64)
- python接口 (63)
- python调用函数 (57)
- python多态 (60)
- python匿名函数 (59)
- python打印九九乘法表 (65)
- python赋值 (62)
- python异常 (69)
- python元祖 (57)