# 基本概念

## 模块&包简介

模块:所谓模块就是一个.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 文件,

 #!/usr/bin/env python
# -*- coding: utf-8 -*-
##############################################################################
# Purpose: to demo underlayer import upperlayer.
##############################################################################
# 目录结构:
# \PHONE
# │ common_util.py -> setup()
# │ __init__.py
# │
# ├─Fax
# │ G3.py -> bar()
# │ __init__.py
# │
# ├─Mobile
# │ Analog.py -> foo()
# │ Digital.py
# │ __init__.py
# │
# ├─Pager
# │ Page.py
# │ __init__.py
# │
# └─Voice
# Isdn.py
# __init__.py
#
############################################################################## from .Analog import foo # ValueError: Attempted relative import in non-package
from ..common_util import setup # ValueError: Attempted relative import in non-package
from ..Fax.G3 import bar # ValueError: Attempted relative import in non-package if __name__ == '__main__': foo()
setup()
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 文件,

 #!/usr/bin/env python
# -*- coding: utf-8 -*-
##############################################################################
# Purpose: to demo underlayer import upperlayer.
##############################################################################
# 目录结构:
# \PHONE
# │ common_util.py -> setup()
# │ __init__.py
# │
# ├─Fax
# │ G3.py -> bar()
# │ __init__.py
# │
# ├─Mobile
# │ Analog.py -> foo()
# │ Digital.py
# │ __init__.py
# │
# ├─Pager
# │ Page.py
# │ __init__.py
# │
# └─Voice
# Isdn.py
# __init__.py
#
############################################################################## # from .Analog import foo # ValueError: Attempted relative import in non-package
# from ..common_util import setup # ValueError: Attempted relative import in non-package
# from ..Fax.G3 import bar # ValueError: Attempted relative import in non-package from Phone.Mobile.Analog import foo
from Phone.common_util import setup
from Phone.Fax.G3 import bar if __name__ == '__main__': foo()
setup()
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文件。

python import注意事项的更多相关文章

  1. python import, from xx import yy

    区别: 用import modulexx/packagexx.moduleyy是导入某一模块,如果想引用模块的内容(class, method,variables...)必须用全名,即 [module ...

  2. python import eventlet包时提示ImportError: cannot import name eventlet

    root@zte-desktop:/home/ubuntu/python-threads# cat eventlet.py #!/usr/bin python import eventlet from ...

  3. python import 模块异常问题

    新项目开始了,(tornado,python) 结果出现了一个比较诡异的问题. import 自己的在conf文件夹下配置文件settings的时候, from conf.settings impor ...

  4. Python import / pyd / dll

    使用Python import 模块时, 先会在模块的搜索path里依次搜索(前面会覆盖之后出现的同名模块),次序为: 1. 程序的主目录(交互模式下当前的工作目录或 脚本文件所在的目录) 2. 环境 ...

  5. 【转】python import的用法

    [转自http://blog.sina.com.cn/s/blog_4b5039210100ennq.html] 在python用import或者from...import来导入相应的模块.模块其实就 ...

  6. python import media模块

    安装PyGraphics包 (python import media模块)有一段代码要import media,打开python自带的IDLE,输入: >>>import media ...

  7. Python: import vs from (module) import function(class) 的理解

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

  8. python import自定义模块方法

    转自:http://www.cnitblog.com/seeyeah/archive/2009/03/15/55440.html python包含子目录中的模块方法比较简单,关键是能够在sys.pat ...

  9. python import自己编写的模块:import json和simplejson

    python import的模块都是库里面的,而自己的模块也可以添加 比如python的json处理,库里没有json文件,import json不行. 网上大部分人告诉你处理json用 dumps和 ...

随机推荐

  1. Bias vs. Variance(4)---根据是high bias还是high variance问题来判断接下来做些什么

    怎么区分哪些措施对我们有用呢?----首先根据learning curve来判断你的问题是high bias or variance 当你的算法是high bias问题时,如果你get more tr ...

  2. PHP——封装Curl请求方法支持POST | DELETE | GET | PUT 等

    前言 Curl:  https://www.php.net/manual/en/book.curl.php curl_setopt: https://www.php.net/manual/en/fun ...

  3. Java线程调度方式

    在Java多线程环境中,为保证所有线程的执行能按照一定的规则执行,JVM实现了一个线程调度器,它定义了线程调度的策略,对于CPU运算的分配都进行了规定,按照这些特定的机制为多个线程分配CPU的使用权. ...

  4. Zookeeper选举(fastleaderelection算法)

    1.选举相关概念: 选票:(myid,zxid,当前节点选取轮次,被推举服务器选举轮次,状态(looking)). 选举发生情况:启动时选举,运行时选举. 外部投票:其他服务器发送来的投票. 内部投票 ...

  5. 2019-2020-1 20199302《Linux内核原理与分析》第五周作业

    一.用户态.内核态和中断 1.一般现代cpu都有几种不用的指令执行级别 2.在高执行级别下,代码可以执行特权指令,访问任意的物理地址,这种CPU执行级别就对应着内核态. 3.在相应的低级别执行状态下, ...

  6. info命令

    info命令也可以查看命令的信息,但是和man命令不同,info命令如同一本书,一个命令只不过是书中的一个章节. 1.基本结构: 输入:info ls ls命令只不过是整个文档的10.1章节. 而在章 ...

  7. aix 10代oracle zabbix2.4.4 日志监控

    同一类型的监控项,zabbix 2.4的客户端也支持日志监控,可是在参数个数上有问题,如果把所有参数都放满,监控项会提示too mant parameters,无法 生效取数据, 对于不同的正则式.m ...

  8. 配置django的环境实现外部脚本调用django中的模型类

    通过导入os模块,os设置django的settings文件,配置好django项目的环境,然后执行django.set_up()使环境生效,然后就可以导入模型类,使用增删改查

  9. leetcode解题报告(31):Kth Largest Element in an Array

    描述 Find the kth largest element in an unsorted array. Note that it is the kth largest element in the ...

  10. Three.js中的group,obj,模型中layers层级与相机

    目录 Three.js中的group,obj,模型中layers层级与相机 layers group中的.layers.mask设置 一些设想 Three.js中的group,obj,模型中layer ...