# 基本概念

## 模块&包简介

模块:所谓模块就是一个.py文件,用来存放变量,方法的文件,便于在其他python文件中导入(通过import或from)。
包(package): 包是更大的组织单位,用来组织区别管理多个模块文件。
import 用来导入模块
from 用于从模块中导入方法(全部或部分),也可用as 重命名导入的方法

## import & from使用方法

* import使用方法:

*import 模块 [as  别名模块]

*import 包.[N包].模块;

注:import 导入 最后一个必须是模块,而不能以包结尾

  1. a)导入单模块文件(import 模块 [as  别名模块])import导入单模块文件后,在import时会执行模块中的代码(从上到下)
  2. b)导入包中的模块(import 包.[N包].模块)import导入包中的模块时,首先会执行包下的__init__.py 注:__init__.py :用来给包做一些初始化的工作。可以为空,但必须要有
  3. c)导入 包.包.模块import导入多层包中的模块时,会执行各包下的__init__.py
  4. d)导入 包.包 出错

* from使用方法:

*from 包.[..包]   import 模块

*from 包.模块  import 方法

*from 模块 import 方法。

注:from 包 import *时,受__init__.py中的__all__影响,没有列出来的模块是没法导入引用的,该参数可写在模块文件中,不写表示可导出所有(即不受限),若要限制 import * 只导部分class、def等,可以在该模块的.py文件中声明 __all__ = ['class1', 'class2']

# Python 包内的导入问题(绝对导入和相对导入)

基本概念

Python 中的包,即包含 __init__.py 文件的文件夹。

对于 Python 的包内导入,即包内模块导入包内模块,存在绝对导入和相对导入问题。

普通 Python 模块的搜索路径

1. 在当前模块所在路径中搜索导入模块

2. 在环境变量 PYTHONPATH 指定的路径列表中搜索导入模块

3. 在 sys.path 指定的路径列表中搜索导入模块

Python import 的步骤

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

1. 如果 import A,检查 sys.modules 中是否已经有 A,如果有则不加载,如果没有则为 A 创建 module 对象,并加载 A,即可以重复导入,但只加载一次。
2. 如果 from A import B,先为 A 创建 module 对象,再解析 A,从中寻找 B 并填充到 A 的 __dict__ 中。

相对导入与绝对导入

绝对导入的格式为 import A.B 或 from A import B,相对导入格式为 from .A import B 或 from ..X import Y,. 代表当前模块,.. 代表上层模块,... 代表上上层模块,依次类推。

不能理解为在当前目录中查找,也不能理解为在上一层目录中查找

相对导入对于包的维护优势

相对导入可以避免硬编码带来的包维护问题,例如我们改了某一层包的名称,那么其它模块对于其子包的所有绝对导入就不能用了,但是采用相对导入语句的模块,就会避免这个问题。

需要注意:存在相对导入语句的模块,是不能直接运行的。 例如,对于如下层次结构的 Digital.py 文件,

 1 #!/usr/bin/env python
 2 # -*- coding: utf-8 -*-
 3 ##############################################################################
 4 # Purpose: to demo underlayer import upperlayer.
 5 ##############################################################################
 6 # 目录结构:
 7 #      \PHONE
 8 #      │  common_util.py   -> setup()
 9 #      │  __init__.py
10 #      │
11 #      ├─Fax
12 #      │      G3.py        -> bar()
13 #      │      __init__.py
14 #      │
15 #      ├─Mobile
16 #      │      Analog.py    -> foo()
17 #      │      Digital.py
18 #      │      __init__.py
19 #      │
20 #      ├─Pager
21 #      │      Page.py
22 #      │      __init__.py
23 #      │
24 #      └─Voice
25 #              Isdn.py
26 #              __init__.py
27 #
28 ##############################################################################
29
30 from .Analog import foo          # ValueError: Attempted relative import in non-package
31 from ..common_util import setup  # ValueError: Attempted relative import in non-package
32 from ..Fax.G3 import bar         # ValueError: Attempted relative import in non-package
33
34 if __name__ == '__main__':
35
36     foo()
37     setup()
38     bar()

如果上述代码直接运行,将导致 ValueError 异常,

ValueError: Attempted relative import in non-package

这是因为:一个模块直接运行,Python 认为这个模块就是顶层模块,不存在层次结构,所以找不到其它的相对路径。

而要正确运行,就要显式的指定路径,如下,

C:\workspace\X_python>python -m Phone.Mobile.Digital
This is foo() from Phone.Mobile.Analog
This is setup() from Phone.common_util
This is bar() from Phone.Fax.G3

当然,我们一般不会直接运行包内的某个模块,这里只是做个说明。

绝对导入对于包维护的劣势

例如,对于如下层次结构的 Digital.py 文件,

 1 #!/usr/bin/env python
 2 # -*- coding: utf-8 -*-
 3 ##############################################################################
 4 # Purpose: to demo underlayer import upperlayer.
 5 ##############################################################################
 6 # 目录结构:
 7 #      \PHONE
 8 #      │  common_util.py   -> setup()
 9 #      │  __init__.py
10 #      │
11 #      ├─Fax
12 #      │      G3.py        -> bar()
13 #      │      __init__.py
14 #      │
15 #      ├─Mobile
16 #      │      Analog.py    -> foo()
17 #      │      Digital.py
18 #      │      __init__.py
19 #      │
20 #      ├─Pager
21 #      │      Page.py
22 #      │      __init__.py
23 #      │
24 #      └─Voice
25 #              Isdn.py
26 #              __init__.py
27 #
28 ##############################################################################
29
30 # from .Analog import foo          # ValueError: Attempted relative import in non-package
31 # from ..common_util import setup  # ValueError: Attempted relative import in non-package
32 # from ..Fax.G3 import bar         # ValueError: Attempted relative import in non-package
33
34 from Phone.Mobile.Analog import foo
35 from Phone.common_util import setup
36 from Phone.Fax.G3 import bar
37
38 if __name__ == '__main__':
39
40     foo()
41     setup()
42     bar()

上述代码可以直接运行。
但是,绝对导入的硬编码模式,如果在包中存在很多 Digital.py 类似模块,都采用了 from Phone.common_util import setup 的语句,如果有一天要更改 common_util 包(文件夹)的名字,那么会影响所有相关的代码。而采用相对导入就没有这个问题。

不过,绝对导入更清晰,如果包不是特别复杂,不是特别易变,那么还是建议采用绝对导入。

相对引用注意事项

1、相对引用发生在package内部,引用模块那一级一定要有__init__.py

2、调用的脚本的位置一定要在package外,如果脚本在引用模块那一级,实际上是找不到上一级的东西的,会报错。

  ValueError: Attempted relative import in non-package。

3、使用相对引用的模块,不能直接作为脚本跑,否则会报错

  ValueError: Attempted relative import in non-package。

  解决方法一: import 该脚本

  解决方法二:python -m 该脚本,也类似import。

相对引用原理

stackoverflow中有解释:relative import依赖文件__name__,而如果跑那个脚本的话,文件名字就成了__main__,这样__package__会被设为None,而相对引用依赖__package__的值,就找不到相对引用的位置了,会报Non-package的错误,在命令行中可以用-m跑,意思是把它当作一个模块。

可以在模块当中定义一个变量__all__:

    使用__all__的影响:  后面的[]里面写什么函数名,使用from 模块名 import *方式导入时导入什么  __all__如果没有这个变量将全部导入(__all__仅限 于from 模块名 import *这种导入方式)

加__all__示例:

1
2
3
4
5
6
7
1 __all__ = ["demo"]
2 def demo():
3
4     print("demo")
5
6 def demo1():
7     print("demo1")

  运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
In [1]: from TT import *
In [2]: demo()
demo
In [3]: demo1()
-----------------------------------------------------------------------
NameError                             Traceback (most recent call last)
<ipython-input-3-a8330644fa2e> in <module>()
----1 demo1()
NameError: name 'demo1' is not defined
In [4]:

不加__all__示例:

1
2
3
4
5
6
1 def demo():
 2
 3     print("demo")
 4    
 5 def demo1():
 6     print("demo1")

  运行结果:

1
2
3
4
5
6
7
In [1]: from TT import *
In [2]: demo()
demo
In [3]: demo1()
demo1

.pyc文件的介绍:

导入时会产生一个.pyc的字节码文件,此文件是当第一次导入时python解释器会将被导入的模块预解释成字节码的文件,下次再导入时python解释器则不会做预解释而是直接拿.pyc文件使用,这样就不会每次导入时做解释的操作,节省时间,当修改模块文件的内容时,python解释器会根据.pyc文件和模块的修改时间判断有没有对模块做修改,如果模块的修改时间比.pyc文件的晚说明模块已经被修改  Python解释器会将模块重新解释成.pyc文件。

转载于:https://www.cnblogs.com/linkenpark/p/10909452.html

python import注意事项相关推荐

  1. gpt用pyQT和python 写待办事项程序,回头把我自己写的改造一下

    首先,需要安装以下库: - PyQt5:用于创建桌面应用程序的GUI界面 - sqlite3:用于连接和操作SQLite数据库 然后,可以按照以下步骤来实现待办事项程序: 1. 创建一个SQLite数 ...

  2. python import from class_Python: import vs from (module) import function(class) 的理解

    Python: Import vs From (module) import function(class) 本文涉及的 Python 基本概念: Module Class import from . ...

  3. python怎么封装方法然后调用_Python实现封装打包自己写的代码,被python import

    1.新建一个文件夹example,里面放入要打包的.py文件,以及必需的_init_.py. 代码如下: # -*- coding: utf-8 -*- """ Crea ...

  4. python import出错_Python ImportError: cannot import name urlopen错误分析

    在学习python的socket编程过程中遇到一个错误,错误的提示信息如下: ImportError: cannot import name urlopen,出现该问题的原因,主要是因为我的目录下有一 ...

  5. import的用法python_Python导入模块,Python import用法(超级详细)

    Python导入模块,Python import用法(超级详细) 使用 Python 进行编程时,有些功能没必须自己实现,可以借助 Python 现有的标准库或者其他人提供的第三方库.比如说,在前面章 ...

  6. boost::python::import相关的测试程序

    boost::python::import相关的测试程序 实现功能 C++实现代码 实现功能 boost::python::import相关的测试程序 C++实现代码 #include <boo ...

  7. python import 路径_python import 上级目录的导入

    python import 上级目录的导入,路径,上级,文件,目录,递归 python import 上级目录的导入 易采站长站,站长之家为您整理了python import 上级目录的导入的相关内容 ...

  8. 关于python import的sys.path路径问题

    关于python import的sys.path路径问题 sys.path 先说一下 sys.path 这个变量,该变量需要导入 sys 官方库方可使用,它是一个列表,是当前 python 文件 im ...

  9. python import 错误 TypeError: 'module' object is not callable

    python import 错误 TypeError: 'module' object is not callable 在这里,有 Person.py test.py; 在 test.py 里面 im ...

最新文章

  1. X86虚拟化之三种服务器虚拟化战略架构
  2. socket什么情况下可读
  3. ·XP注册表修改大全
  4. proxifier代理失败原因_上海财务代理
  5. [渝粤教育] 中国地质大学 面向对象程序设计 复习题
  6. SCCM2012系列之二,SCCM2012部署前的Active Directory准备
  7. webpack教程——css的加载
  8. Android视频加密
  9. Python 3.7 pygame 下载方法
  10. 爬取链家二手房信息【爬虫模板】
  11. 功率半导体器件的研究意义
  12. 如何快速压缩PPT文件?
  13. 数据分析之第三方支付业务
  14. 成考专升本高等数学公式笔记
  15. 论文笔记 SiamMask : Fast Online Object Tracking and Segmentation: A Unifying Approach
  16. Firefly-RK3288开发板Android编译环境搭建开荒
  17. Word中插入多张图片/论文图片排版的方法
  18. 用Python向MongoDB中插入大csv文件
  19. 简述python在量化金融中应用_Python金融量化
  20. 苹果隐藏app_更新完iOS14,这9个隐藏黑科技功能,你一定还不知道

热门文章

  1. Java实现微信小程序校验图片是否含有违法违规内容
  2. 【无标题】两个路由器不同网段互通
  3. SQL Server 数据库修复专家SQLRescue
  4. 一些 差分线的 线距 和 线宽
  5. Allegro如何使用快捷键快速切换走线线宽操作指导
  6. android的视频直播,Android进行视频,直播播放
  7. 1000人 规模园区网设计
  8. 【每日蓝桥】13、一三年省赛Java组真题“黄金连分数”
  9. Docker|Maven编译推送Docker服务器生成镜像
  10. 紫薇星上的数据结构(10)