首页 后端开发 Python教程 python中import学习备忘笔记

python中import学习备忘笔记

Feb 03, 2017 pm 04:05 PM

前言

在python的模块有两种组织方式,一种是单纯的python文件,文件名就是模块名,一种是包,包是一个包含了若干python文件的目录,目录下必须有一个文件__init__.py,这样目录名字就是模块名,包里的python文件也可以通过包名.文件名的方式import

import语法

import语法有两种

1、直接import模块

import Module
import Module as xx
登录后复制

2、从模块import对象(下级模块,类,函数,变量等)

from Module import Name
from Module immport Name as yy
登录后复制

as语法是用来设置对象(这里用对象泛指模块,类,函数等等)别名,import将对象名字引入了当前文件的名字空间

假设有如下目录结构

├── A.py
└── pkg
 ├── B.py
 └── __init__.py
登录后复制

在当前目录下,以下语句都是有效的

import A
import pkg
import pkg.B
from pkg import B
登录后复制

为了简化讨论,下面将不会对as语法进行举例

import步骤

python所有加载的模块信息都存放在sys.modules结构中,当import一个模块时,会按如下步骤来进行

如果是import A,检查sys.modules中是否已经有A,如果有则不加载,如果没有则为A创建module对象,并加载A

如果是from A import B,先为A创建module对象,再解析A,从中寻找B并填充到A的__dict__中

嵌套import

在import模块时我们可能会担心一个模块会不会被import多次,假设有A,B,C三个模块,A需要import B和C,B又要import C,这样A会执行到两次import C,一次是自己本身import,一次是在import B时执行的import,但根据上面讲到的import步骤,在第二次import时发现模块已经被加载,所以不会重复import

但如下情况却会报错

#filename: A.py
from B import BB
class AA:pass
 
#filename: B.py
from A import AA
class BB:pass
登录后复制

这时不管是执行A.py还是B.py都会抛出ImportError的异常,假设我们执行的是A.py,究其原因如下

文件A.py执行from B import BB,会先扫描B.py,同时在A的名字空间中为B创建module对象,试图从B中查找BB

扫描B.py第一行执行from A import AA,此时又会去扫描A.py

扫描A.py第一行执行from B import BB,由于步骤1已经为B创建module对象,所以会直接从B的module对象的__dict__中获取BB,此时显然BB是获取不到的,于是抛出异常

解决这种情况有两种办法,

将from B import BB改为import B,或将from A import AA改为import A

将A.py或B.py中的两行代码交换位置

总之,import需要注意的是,尽量在需要用到时再import

包的import

当一个目录下有__init__.py文件时,该目录就是一个python的包

import包和import单个文件是一样的,我们可以这样类比:

import单个文件时,文件里的类,函数,变量都可以作为import的对象

import包时,包里的子包,文件,以及__init__.py里的类,函数,变量都可以作为import的对象

假设有如下目录结构

pkg
├── __init__.py
└── file.py
登录后复制

其中__init__.py内容如下

argument = 0
class A:pass
登录后复制

在和pkg同级目录下执行如下语句都是OK的

>>> import pkg
>>> import pkg.file
>>> from pkg import file
>>> from pkg import A
>>> from pkg import argument
登录后复制

但如下语句是错误的

>>> import pkg.A
>>> import pkg.argument
登录后复制

报错ImportError: No module named xxx,因为当我们执行import A.B,A和B都必须是模块(文件或包)

相对导入和绝对导入

绝对导入的格式为import A.B或from A import B,相对导入格式为from . import B或from ..A import B,.代表当前模块,..代表上层模块,...代表上上层模块,依次类推。当我们有多个包时,就可能有需求从一个包import另一个包的内容,这就会产生绝对导入,而这也往往是最容易发生错误的时候,还是以具体例子来说明

目录结构如下

app
├── __inti__.py
├── mod1
│ ├── file1.py
│ └── __init__.py
├── mod2
│ ├── file2.py
│ └── __init__.py
└── start.py
登录后复制

其中app/start.py内容为import mod1.file1

app/mod1/file1.py内容为from ..mod2 import file2

为了便于分析,我们在所有py文件(包括__init__.py)第一行加入print __file__, __name__

现在app/mod1/file1.py里用到了相对导入,我们在app/mod1下执行python file1.py或者在app下执行python mod1/file1.py都会报错ValueError: Attempted relative import in non-package

在app下执行python -m mod1.file1或python start.py都会报错ValueError: Attempted relative import beyond toplevel package

具体原因后面再说,我们先来看一下导入模块时的一些规则

在没有明确指定包结构的情况下,python是根据__name__来决定一个模块在包中的结构的,如果是__main__则它本身是顶层模块,没有包结构,如果是A.B.C结构,那么顶层模块是A。

基本上遵循这样的原则

如果是绝对导入,一个模块只能导入自身的子模块或和它的顶层模块同级别的模块及其子模块

如果是相对导入,一个模块必须有包结构且只能导入它的顶层模块内部的模块

有目录结构如下

A
├── B1
│ ├── C1
│ │ └── file.py
│ └── C2
└── B2
登录后复制

其中A,B1,B2,C1,C2都为包,这里为了展示简单没有列出__init__.py文件,当file.py的包结构为A.B1.C1.file(注意,是根据__name__来的,而不是磁盘的目录结构,在不同目录下执行file.py时对应的包目录结构都是不一样的)时,在file.py中可采用如下的绝对的导入

import A.B1.C2
import A.B2
登录后复制

和如下的相对导入

from .. import C2
from ... import B2
登录后复制

什么情况下会让file.py的包结构为A.B1.C1.file呢,有如下两种

在A的上层目录执行python -m A.B1.C1.file, 此时明确指定了包结构

在A的上层目录建立文件start.py,在start.py里有import A.B1.C1.file,然后执行python start.py,此时包结构是根据file.py的__name__变量来的

再看前面出错的两种情况,第一种执行python file1.py和python mod1/file1.py,此时file.py的__name__为__main__ ,也就是说它本身就是顶层模块,并没有包结构,所以会报错

第二种情况,在执行python -m mod1.file1和python start.py时,前者明确告诉解释器mod1是顶层模块,后者需要导入file1,而file1.py的__name__为mod1.file1,顶层模块为也mod1,所以在file1.py中执行from ..mod2 import file2时会报错 ,因为mod2并不在顶层模块mod1内部。通过错误堆栈可以看出,并不是在start.py中绝对导入时报错,而是在file1.py中相对导入报的错

那么如何才能偶正确执行呢,有两种方法,一种是在app上层目录执行python -m app.mod1.file1,另一种是改变目录结构,将所有包放在一个大包中,如下

   
app
├── pkg
│ ├── __init__.py
│ ├── mod1
│ │ ├── __init__.py
│ │ └── file1.py
│ └── mod2
│ ├── __init__.py
│ └── file2.py
└── start.py
登录后复制

start.py内容改成import pkg.mod1.file1,然后在app下执行python start.py

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家学习或者使用python能带来一定的帮助,如有疑问大家可以留言交流。

更多python中import学习备忘笔记相关文章请关注PHP中文网!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它们
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

如何解决Linux终端中查看Python版本时遇到的权限问题? 如何解决Linux终端中查看Python版本时遇到的权限问题? Apr 01, 2025 pm 05:09 PM

Linux终端中查看Python版本时遇到权限问题的解决方法当你在Linux终端中尝试查看Python的版本时,输入python...

如何在10小时内通过项目和问题驱动的方式教计算机小白编程基础? 如何在10小时内通过项目和问题驱动的方式教计算机小白编程基础? Apr 02, 2025 am 07:18 AM

如何在10小时内教计算机小白编程基础?如果你只有10个小时来教计算机小白一些编程知识,你会选择教些什么�...

在Python中如何高效地将一个DataFrame的整列复制到另一个结构不同的DataFrame中? 在Python中如何高效地将一个DataFrame的整列复制到另一个结构不同的DataFrame中? Apr 01, 2025 pm 11:15 PM

在使用Python的pandas库时,如何在两个结构不同的DataFrame之间进行整列复制是一个常见的问题。假设我们有两个Dat...

如何在使用 Fiddler Everywhere 进行中间人读取时避免被浏览器检测到? 如何在使用 Fiddler Everywhere 进行中间人读取时避免被浏览器检测到? Apr 02, 2025 am 07:15 AM

使用FiddlerEverywhere进行中间人读取时如何避免被检测到当你使用FiddlerEverywhere...

什么是正则表达式? 什么是正则表达式? Mar 20, 2025 pm 06:25 PM

正则表达式是在编程中进行模式匹配和文本操作的强大工具,从而提高了各种应用程序的文本处理效率。

Uvicorn是如何在没有serve_forever()的情况下持续监听HTTP请求的? Uvicorn是如何在没有serve_forever()的情况下持续监听HTTP请求的? Apr 01, 2025 pm 10:51 PM

Uvicorn是如何持续监听HTTP请求的?Uvicorn是一个基于ASGI的轻量级Web服务器,其核心功能之一便是监听HTTP请求并进�...

Python中如何通过字符串动态创建对象并调用其方法? Python中如何通过字符串动态创建对象并调用其方法? Apr 01, 2025 pm 11:18 PM

在Python中,如何通过字符串动态创建对象并调用其方法?这是一个常见的编程需求,尤其在需要根据配置或运行...

哪些流行的Python库及其用途? 哪些流行的Python库及其用途? Mar 21, 2025 pm 06:46 PM

本文讨论了诸如Numpy,Pandas,Matplotlib,Scikit-Learn,Tensorflow,Tensorflow,Django,Blask和请求等流行的Python库,并详细介绍了它们在科学计算,数据分析,可视化,机器学习,网络开发和H中的用途

See all articles