python多级目录import_你真的会用Python模块与工具包吗?

在开发过程中,我们无法把所有代码、资源都放在同一个文件中。因此,模块导入在编码中是很常见的。无论是C++、Java,还是Python、Go。

可以把不同功能、不同模块进行分离,当使用的时候,可以通过import关键字在一个模块中使用另外一个模块提供的能力,这能够大大提升代码的开发效率。

尤其是对于Python这种对于模块、工具包依赖较强的编程语言,这一点更为突出。

模块导入,这一点在Python中最为常见的东西对于很多人来说都不屑一顾,但是,你真的彻底理解Python中的import吗?

我可以断言,绝大多数Python开发人员只是使用,却不知所以然。

本文,就来详细、彻底的介绍一下Python模块导入的使用。

模块与工具包

模块(modules)和工具包(packages)这2个概念首当其冲,经常被Python开发者混为一谈。

虽然,二者有很多相同之处,但是还是存在一定差异。因此,要想彻底理解import,首先就需要理解模块与工具包的异同点。

模块

Python官网对于模块的定义如下:

模块具有一个包含任意Python对象的命名空间,通常用作Python代码组织单位的对象。

实际上,一个模块通常对应一个.py文件,模块的真正功能是可以将其导入到其他代码中,并重复使用,例如:

>>> import math
>>> math.pi
3.141592653589793

第一行代码,通过import把math模块导入到代码中,通过math.pi来调用pi这一属性。

这里需要注意,这里写的math.pi不仅是单纯的pi,它还把math充当所有属性保持统一的命名空间。命名空间对于保持代码的可读性和组织性非常有用。

你可以利用 dir来查看命名空间的内容:

>>> import math
>>> dir()
['__annotations__', '__builtins__', ..., 'math']

>>> dir(math)
['__doc__', ..., 'nan', 'pi', 'pow', ...]

除了上述直接导入,我们还可以导入模块下特定的部分:

>>> from math import pi
>>> pi
3.141592653589793

>>> math.pi
NameError: name 'math' is not defined

请注意,这里对比于前一种方式已经发生了一些转变。这里的pi是放置在全局命名空间内,而不是math的命名空间内。

同样,首先看一下Python官网对工具包的定义:

一个Python模块,可以包含子模块或递归地包含子包。从技术上讲,包是具有__path__属性的Python模块。

从定义上可以看出,包仍然是模块。但是,它们还是有一定的区别。

从编码上来讲,Python包需要在目录下创建一个名为__init__.py的文件。

导入模块时,通常不会导入子模块和子包,但是,你可以通过添加__init__.py来将需要导入的子模块和子包囊括进去。

绝对导入与相对导入

from ... import ...这种导入当时在代码中经常会遇到,假如,我们有如下工程:

world/

├── africa/
│ ├── __init__.py
│ └── zimbabwe.py

├── europe/
│ ├── __init__.py
│ ├── greece.py
│ ├── norway.py
│ └── spain.py

└── __init__.py

当想要导入africa时可以这样:

from world import africa

也可以这样:

from . import africa

那么这里面的**点(.)**代表什么含义?

这里的点(.)就是一种相对导入,你可以理解为从当前包中导入africa

相反,绝对导入语句中,需要明确命名当前包:

from world import africa

在编码过程中,你可以选择绝对导入,也可以选择相对导入。只不过,PEP 8风格指南中,建议使用绝对导入。

Python导入路径

这是一个需要重点理解的问题,很多开发者从接触Python开始就是用PyCharm,它对于导入路径已经进行了默认的配置,因此,开发者很难遇到无法导入的问题。

但是,当切换到VS Code、Sublime这些需要较多自行配置的开发工具之后,会发现无法导入,或者因为导入工具包带来的调用错误问题。

Python是如何找到它要导入的模块和包的?

你可以试着输出sys.path,你会发现输出列表中主要包含如下3个部分的位置:

  • 当前脚本目录
  • PYTHON_PATH环境变量
  • 其他与安装相关的目录

通常情况下,Python将对列表进行从头开发遍历,从每个位置中寻找给定的模块,直到第一个匹配为止

由于脚本所在目录始终被排在列表的第一位,因此,导入模块时它会首先从当前目录下进行寻找。

所以,一定不要把自己的代码文件名称与工具包重名。

例如,当前目录有一个名为math.py的文件:

# math.py

def double(number):
return 2 * number

这时候,你导入可以按照预期工作:

>>> import math
>>> math.double(3.14)
6.28

但是,它已经覆盖了Python自带的math标准库。如果我们误认为导入的是标准math模块,去调用pisqrt这些方法,则会报错:

>>> math.pi
Traceback (most recent call last):
File "", line 1, in
AttributeError: module 'math' has no attribute 'pi'>>> math'math' from 'math.py'>

因此,为了避免这个问题,一定小心自己开发代码文件的命名。

创建并安装本地工具包

在Python开发过程中,经常会用到pip安装来自PyPI仓库的工具包,它可以用于全局的工程项目。

除了从仓库下载安装工具包,还可以自行在本地创建工具包,并完成安装。

创建本地安装包只需要创建setup.cfgsetup.py两个项目就行:

# setup.cfg

[metadata]
name = local_structure
version = 0.1.0

[options]
packages = structure

# setup.py

import setuptools

setuptools.setup()

这里的版本名称和版本号可以自行选择。

然后,可以执行下方命令,把创建的安装包安装到本地:

$ python -m pip install -e .

导入样式

为了保持代码的可读性和可维护性,PEP 8提出了一些针对模块导入的规则:

  • 将导入放在文件的顶部
  • 每个导入要分行
  • 将导入分组:首先是标准库导入,然后是第三方导入,最后是本地应用程序或库导入
  • 在每个组中按字母顺序排序导入
  • 绝对导入优先于相对导入
  • 避免使用通配符导入from module import *
# Standard library imports
import sys
from typing import Dict, List

# Third party imports
import feedparser
import html2text

# Reader imports
from reader import URL

资源导入

除了模块和工具包,代码开发过程中,还会经常用到外部资源包,针对外部资源包的导入,可以使用importlib.resources

它是Python 3.7中的标准模块,使用它有2点好处:

  • 使得导入方式更加一致
  • 可以更轻松地访问其他包中的资源文件

例如,

>>> from importlib import resources
>>> with resources.open_text("books", "alice_in_wonderland.txt") as fid:
... alice = fid.readlines()

动态导入

Python是一门动态语言,这也是它的主要特点之一。

动态语言使得你可以在程序运行的时候做很多事情,可以添加属性、重新定义方法、更改模块的文档字符串。

例如,通过修改print()函数,使它不做任何操作:

>>> print("Hello dynamic world!")
Hello dynamic world!

>>> # Redefine the built-in print()
>>> print = lambda *args, **kwargs: None

>>> print("Hush, everybody!")
>>> # Nothing is printed

在上述示例中,print函数就被匿名函数重新定义了。

除了这种方法,还有更为易用的动态导入方式,就是利用importlib

先来看一段示例,

# docreader.py

import importlib

module_name = input("Name of module? ")
module = importlib.import_module(module_name)
print(module.__doc__)

import_module()返回可以绑定到任何变量的模块对象。然后,您可以将该变量视为常规导入的模块。

$ python docreader.py
Name of module? math
This module is always available. It provides access to the
mathematical functions defined by the C standard.

$ python docreader.py
Name of module? csv
CSV parsing and writing.

在每种情况下,该模块都是通过动态导入的import_module()

周期性导入

如果两个或者多个模块互相导入时,就会发生周期性导入。

例如,有两个模块yin.pyyang.py

# yin.py

print(f"Hello from yin")
import yang
print(f"Goodbye from yin")

# yang.py

print(f"Hello from yang")
import yin
print(f"Goodbye from yang")

尝试在交互式命令行下导入yin时会发生下面情况:

>>> import yin
Hello from yin
Hello from yang
Goodbye from yang
Goodbye from yin

有些同学会疑惑,这样互相导入,难道不会无限循环下去吗?

这得益于Python的模块缓存机制,在导入yin之后,会首先把它加入到缓存中,后续再导入,会先去参考缓存区域,避免无限循环。


推荐阅读

或许,这是最强大的一款Python GUI工具

8个小技巧教你提升Python代码质量

5款最强且免费的Python IDE

福利

最近我花费了半个月的时间,整理了1份理论+实践的计算机视觉入门教程,这或许是你见过最好的一份CV教程之一。独家打造、完全免费,需要的同学可以扫码添加我的个人微信,发送“CV”获取~

4150d1cb859ac3c4a73922af865f0ed0.png

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

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

相关文章

八边形点坐标数的lisp_图形学入门第五课:齐次坐标

齐次坐标(Homegeneous Coordinates)在学习齐次坐标之前,我们要先好奇的问一下,为什么要学习齐次坐标。上一节课,我们学习了变换的三种基本形式:旋转,缩放,和切变。但是还有一种特殊的变换:Trans…

对速度的需求,访问现有数据的速度提高了1000倍

了解如何通过使用标准Java 8流和Speedment的In-JVM-Memory加速器将分析数据库应用程序加速1000倍。 Web和移动应用程序有时会很慢,因为后备数据库很慢和/或与数据库的连接施加了延迟。 现代UI和交互式应用程序需要快速后端,并且理想情况下没有可观察到的…

mysqls压力测试怎么用_用 Swagger 测试接口,怎么在请求头中携带 Token?

松哥周末抽空给 Spring Security 系列也录制了一套视频,目录如下:感兴趣的小伙伴戳这里-->Spring BootVue微人事视频教程今天的话题来自一个小伙伴在微信上的提问:看到这个问题,松哥忽然想到我自己之前写过 Spring BootSwagger…

安卓手机背景变黑色怎么改_别着急扔掉旧手机 你的电脑可能需要它

PC玩家中,不少人都会有在玩游戏时观测电脑硬件状态的习惯。比如查看游戏帧数、CPU频率、GPU频率或是温度等。大多数人都是通过第三方软件,在游戏内把监测数据显示到电脑显示屏角落。可就算是在角落,这些数据依旧会阻挡游戏画面,在…

JDeps入门–分析项目的依赖关系

JDeps是Java依赖关系分析工具 ,这是一个命令行工具,它处理Java字节码(意味着.class文件或包含它们的JAR),并分析类之间静态声明的依赖关系。 可以用各种方式过滤结果,并可以将其汇总到包或JAR级别。 JDeps还…

禅道开源版用户手册_Docker搭建开源版禅道以及项目基本流程介绍

对于自学软件测试的同学来说,经常会遇到这样的困惑:测试用例怎么写?有啥好的模板?缺陷提交的模板是什么样的?bug的生命周期是啥?项目的流程是啥?以上这些困惑,在你仔细看完这篇文章后…

f12 卡 谷歌浏览器_抢券第二课:利用浏览器F12获取优惠券请求链接

抢券第二课为什么迟迟不来呢?因为最近京东没有那种神券需要定点抢购的,我也没法测试我的理论。现在京东的券随时可以领取到,我多没法测试的东西不想就这样欺骗你们。所以今天的第二课我们讲一讲神奇的谷歌浏览器F1201 工具准备一、浏览器这里…

Java命令行界面(第5部分):JewelCli

细算在Java命令行处理与Apache的百科全书CLI , args4j , jbock和命令行中先前的文章,我把注意力转向在这个岗位使用JewelCli完成的命令行参数相似的处理Java中。 几个Java命令行处理库使用批注来定义命令行选项。 到目前为止,本系…

dnf用虚拟机会被制裁吗_DNF: 神豪奶妈扬言, 战斗力没有超过他的, 都不配被加buff!...

要说到现在的年轻人们的交友方式绝对少不了游戏交友,以前的人们只要不出门那就是与世隔绝,而现在就算是不出门也可以在网络上结交一大帮朋友,游戏就是现在的年轻人们交友最多的地方之一。科技的发展让游戏进入了一个繁荣的春天,不…

什么叫轻量瓷_为什么说陶瓷是华夏文明的徽章?

一、先说何为徽章?徽,最基本的解释是标志、符号;章,基本释义较多,其之一为佩戴在身上的标志,如领章、胸章等。徽章,也就是佩戴在身上用以表示身份、职业或者荣誉的标志。徽章的作用是明确身份、…

Java命令行界面(第10部分):picocli

picocli主页面将picocli描述为“强大的微小命令行界面”,“ picocli”是一个文件Java框架,用于解析命令行参数并生成精美,易于定制的用法帮助消息。 有颜色。” 这篇文章简要介绍了如何使用Picocli 0.9.7处理Java代码中的命令行参数。 像本系…

workunit 的指的工作单元是什么_分频器是做什么用的?

由于现在的音箱几乎都采用多单元分频段重放的设计方式,所以必须有一种装置,能够将功放送来的全频带音乐信号按需要划分为高音、低音输出或者高音、中音、低音输出,才能跟相应的喇叭单元连接,分频器就是这样的装置。如果把全频带信…

合并不同gdb下的相同要素_GDB调试学习

简介GDB是GCC的调试工具。其功能如下:启动程序,使程序按自定义形式运行;使程序停止指定断点位置;程序停止后,检查程序执行中的相应情况;动态改变程序执行环境。gdb调试能进行GDB调试,一般在编译…

endnote文献顺序编号不对_把Endnote装进大脑:行走的文献管理者

是否还迷失在茫茫的文献海洋,东翻西找,仍无法获得需要的文献信息?是否还在半手动导入参考文献,费时费力?别着急,文献管理神器-Endnote轻松帮你搞定这些问题。把Endnote“装进”大脑,你就能成为行…

蔡司三坐标_蔡司三坐标测针的安装指南

1、装配和辅助工具合适的辅助工具可以在组装测针组时有效防止各部件的损坏,确保安装的安全进行。下面是几种最重要的装配和辅助工具。2、正确调整MT/VAST吸盘MT/VAST吸盘可以通过顶部的三个螺丝进行旋转调节。必须使用不超过2Nm的扭力紧固,为了防止螺丝的…

三电平igbt死区时间计算_IGBT基础与运用-2

IGBT基础与运用-1尝试去计算IGBT的开启过程,主要是时间和门电阻的散热情况。C.GE 栅极-发射极电容C.CE 集电极-发射极电容C.GC 门级-集电极电容(米勒电容)Cies CGE CGC 输入电容Cres CGC 反向电容Coes CGC CCE 输出电容根据充电的详细过程,可以下图…

在2017年从Maven工件生成P2存储库

几年前,我写了一篇博客文章,介绍如何基于Maven工件生成P2存储库。 如今,这种描述的方法已经过时了,我想展示一种基于p2-maven-plugin的新方法,该方法是为解决该问题而创建的。 Maven构建生命周期中的P2-Maven-Plugin集…

循环次数几次_圆柱模板循环使用次数是多少呢

对于同一处做同样的工程,如果需要使用的是圆柱模板,用户一定考虑到底该进多少货,备多少料(圆柱模板)呢?这就需要考虑到圆柱模板循环使用次数和错开的程度来进行决定的?建筑圆柱模板能周转几次?这可能是所有…

network 拦截不到东西是怎么做到的?_都说读中职院校学不到东西,中职学生到底是怎么学习的?...

中职院校在社会中的影响一直并不是很好,一直都是负面影响高于正面影响,那么,我们不禁就要问了,一直在喊提升中职院校的教学质量,质量提升到哪里去了呢!那些中职院校里的学生到底又是怎么学习的呢&#xff1…

数组中查找並返回数组_java数组查找常见情况

一.最简单的查找元素方法(依次比较):给一个数组,在数组里面查找某个元素在数组中的位置,并返回它的位置。public static void main(String[] args) {int arr[] new int[]{12, 4, 54, 57, 87, 3, 41, 1, 3, 4, 1, 3, 4…