python模块与包的调用

模块(module)

什么是模块

一个 .py文件 就是一个模块(Module)。
在开发过程中我们不会把所有的代码都写在一个 .py文件 中。随着代码量的增大,可以按照功能将函数或者类分开存放到不同的 .py文件 中。
?
这样代码更方便管理,以及后期的维护,也便于其他程序来调用当前已经实现的功能~
?
在开发过程中,我们也经常引用其他模块,例如:time,os,configparser,re 等等
在Python中模块一般有如下3种:
1)Python内置模块
2)第三方模块
3)自定义模块

模块的导入

import 语句

导入模块的语句如下:

import module1[, module2[,... moduleN]
或
import module1
import module2
...
import moduleN

具体使用哪一种方式根据个人习惯而定,导入模块后,模块中的方法或者类可以通过 模块名.方法() 直接调用~

>>> import time
>>> time.time()                     # time() 为 time模块中的方法
1545832129.4365451
>>> import datetime
>>> datetime.datetime.now()      # datetime 为datetime模块中的类
datetime.datetime(2018, 12, 26, 21, 49, 2, 805953)

当我们使用 import 语句导入模块时,Python解释器首先会去内置名称空间中寻找,即判断导入的模块是不是内置模块(例如time模块就是Python内置模块),然后再去 sys.path 列表中定义的路径从前往后寻找 .py文件
如下是在个人笔记本上输出的 sys.path列表:

# pycharm中进行输出:
[‘/Users/baby/PycharmProjects/untitled/module‘,
‘/Users/baby/PycharmProjects/untitled‘,
‘/usr/local/Cellar/python/3.7.1/Frameworks/Python.framework/Versions/3.7/lib/python37.zip‘,
‘/usr/local/Cellar/python/3.7.1/Frameworks/Python.framework/Versions/3.7/lib/python3.7‘,
‘/usr/local/Cellar/python/3.7.1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/lib-dynload‘, ‘/usr/local/lib/python3.7/site-packages‘,
‘/Applications/PyCharm.app/Contents/helpers/pycharm_matplotlib_backend‘]

# 在终端进行输出:
>>> sys.path
[‘‘, ‘/usr/local/Cellar/python/3.7.1/Frameworks/Python.framework/Versions/3.7/lib/python37.zip‘,
‘/usr/local/Cellar/python/3.7.1/Frameworks/Python.framework/Versions/3.7/lib/python3.7‘,
‘/usr/local/Cellar/python/3.7.1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/lib-dynload‘,
‘/usr/local/lib/python3.7/site-packages‘]
  • 可以看到 sys.path 在pycharm中的输出和在终端的输出略有区别,在pycharm中,pycharm会自动将当前项目的路径添加在 sys.path 列表的最前面。所以若是在当前路径下存在与要引入模块同名的文件,就会把要引入的模块屏蔽掉~
    ?
    sys.path 列表中其中一个路径下的文件 如下:

    ?  ~ ls /usr/local/Cellar/python/3.7.1/Frameworks/Python.framework/Versions/3.7/lib/python3.7
    LICENSE.txt                             fileinput.py                            re.py
    __future__.py                           fnmatch.py                              reprlib.py
    __phello__.foo.py                       formatter.py                            rlcompleter.py
    ...
    ...

import 的过程

现在我自己编辑了一个模块 sftp,内容如下:

server_ip = ‘192.168.0.30‘

def get_file():
    print(‘ddownload file ...‘)

然后在 main.py文件(与sftp.py在同一个路径下) 中进行导入:

import sftp

?
在 import sftp 时,Python解释器会首先创建一个新的名称空间,这个名称空间用于存放 sftp 模块中定义的名字,然后在该名称空间中执行 sftp.py 文件。
例如现在在 sftp 模块中添加 print 语句,然后执行 main.py文件:

# sftp.py
server_ip = ‘192.168.0.30‘

def get_file():
    print(‘ddownload file ...‘)

print(‘hello ....‘)

# main.py
import sftp

# 执行 main.py 后会有如下输出:
hello ....

import语句 可以理解为定义了一个变量,而该变量就指向对应的名称空间,通过使用这个变量来引用该名称空间中的方法及变量~
?
import sftp 之后,注意区分新创建的名称空间和当前的名称空间,示例如下:

# sftp.py
server_ip = ‘192.168.0.30‘

def get_file():
    print(‘ddownload file ...‘)

# main.py
import sftp

server_ip = ‘1.2.3.4‘

print(server_ip)
print(sftp.server_ip)

# 执行 main.py 后会有如下输出:
1.2.3.4
192.168.0.30
  • 注意,sftp.py 中的 server_ip 和 main.py文件中的 server_ip 位于不同的名称空间下,所以名称相同不会冲突;当然调用的方式也不同,当前文件中的 server_ip 可以直接引用,sftp模块中的 server_ip 需要使用 模块名.变量名 的方式来引用(sftp.server_ip)
    ?
    还有一点需要注意,若是一个模块在当前文件中被导入多次,那么模块中的代码只会被执行一次,而不会多次执行~。那是因为第一次导入,模块中的方法和变量已经加载到内存中,之后的导入不会重复加载~

重命名模块

在导入模块的时候还可以对模块进行重命名,以方便使用;若是当前文件中存在同名的方法或变量,也可以通过这种方式避免冲突~

import datetime as date
date.datetime.now()

from import

from import 语法如下:

from modname import name1[, name2[, ... nameN]]

import语句的导入会新建一个名称空间,将模块中的名称存放在该名称空间中,而 ‘from modname import name1, name2‘ 则会将name1 和 name2 单个导入到当前的名称空间中。既然是导入到当前的名称空间中,那就可以直接拿来使用,前面不需要再添加模块名称。

from datetime import datetime
print(datetime.now())    # 不需要写成 datetime.datetime.now()

?
若是 from … import 导致了名称重读,则哪一个后定义,就使用哪一个

def foo():
    pass
from demo import foo

# 这里引用 foo 函数,会使用 demo 模块中的 foo函数

#############
from demo import foo
def foo():
    pass

# 这里引用 foo 函数,会使用 当前文件中的 foo函数

包(package)

简单而言,Python中的包(Package)就是一个目录,里面存放了 .py文件,外加一个 __init__.py。通过目录的方式来组织众多的模块,包就是用来管理和分类模块的。引入包之后,还有一个好处就是 同名的模块可以放在不同的包下,以避免名称冲突~
?
例如现在有如下3个包,ROOT,pk_1,pk_2:

模块m1的全名是:ROOT.pk_1.m1;模块m2的全名则是:ROOT.pk_2.m2 ~

init.py 文件的作用

在每一个包目录下,都应该有一个 __init__.py 文件,若这个文件不存在,那么这个目录只是一个目录而不是一个包。__init__.py 文件可以是空文件,也可以有 Python 代码,原则是尽量保持 __init__.py 文件的精简~
?
导入包的语句如下:

import package 

# 或引入包下的某一个模块
from package import module

import package 或者 from package import module 都会执行package 包下的 __init__ 文件
?

现在有如下目录结构:

├─ROOT
│  ├─pk_1
│  │  ├─__init__.py
│  │  ├─m1.py
│  ├─pk_2
│  │  ├─__init__.py
│  │  └─m2.py
│  ├─__init__.py
│  ├─test.py

pk_1 和 pk_2 包中的 __init__.py 文件都为空,ROOT包下的 test.py 想要使用 pk_1 包下 m1模块中的方法,可以使用如下语句:

from pk_1 import m1
m1.fun_1()        # fun_1() 为m1模块中的方法

但是使用如下语句,就会抛出异常:

from pk_1 import *
m1.fun_1()

# 异常信息:
NameError: name ‘m1‘ is not defined
##############################
import pk_1
pk_1.m1.fun_1()

# 异常信息:
AttributeError: module ‘pk_1‘ has no attribute ‘m1‘

这时候可以在 pk_1 包中的__init__.py 中 进行 包提升(在包中提升导入权限),pk_1 包的 __init__.py 文件内容如下:

from pk_1.m1 import fun_1

然后在 test.py 文件中可以直接通过包名引入方法:

# 1)
from pk_1 import fun_1 # 或 from pk_1 import *
fun_1()

# 2)
import pk_1
pk_1.fun_1()

?
这个就是 包中 __init__.py 文件存在的意义,可以将相关的导入语句 或 提升导入权限的语句 写在 __init__.py文件中,这样使用者就不需要了解包中的内部结构,可以直接通过包名 调用该包(package)中某个模块的方法~
?
还可以在 包中 __init__.py 文件中使用 __all__ 列出需要导入的模块,例如在 pk_1 包中的 __init__.py文件中添加 __all__ 变量:

__all__ = [‘m2‘]

然后在 test.py 文件中就可以使用 from pk_2 import * 一次性导入 __all__变量中列出的模块:

from pk_2 import *
m2.fun_2()

若是 pk_2 包的 __init__.py 文件已经对 fun_2 方法做了提升:

# pk_2 包的 \_\_init\_\_.py 内容
from pk_2.m2 import fun_2

这样在 test.py 中 import * 后可直接使用该方法:

from pk_2 import *
fun_2()

注意:当 __init__.py 中定义了 __all__ 变量时,import * 只会导入 __all__中列出的模块

包中的模块调用

现在有如下目录结构:

├─log
│  ├─util
│  │  ├─__init__.py
│  │  ├─a.py
│  │  ├─b.py
│  ├─__init__.py
│  ├─test.py

在test中引入 a模块:

from util import a

在 a 模块中又引入了 b 模块:

import b

这样的话在执行 test 文件时就会报错,ModuleNotFoundError: No module named ‘b‘,说无法找到b模块。
?
这是因为 在执行 test 时,sys.path 中的路径不包含 util 下的路径,所以在 a.py 文件中 import b 模块时就会报错(若是直接执行的是 a.py 文件就不会有问题)。在 a模块 中引入 b 模块的正确的写法是:

from util import b

当然这个时候 a.py 文件就不能再单独运行了,运行时就会报错
?
Tip:在 a.py 文件中 使用 "from util import b" 导入模块 b,这个时候若是直接执行 a.py 文件就会报错,因为 a.py 文件本身就位于util路径下,sys.path(执行 a.py 时的sys.path)中有util路径,但是 ‘from util‘ 是找不到util的,util 位于 sys.path 的某个路径下时,‘from util‘ 才能找到util ~
?
若是现在 主执行文件 本身就位于项目目录下的某个包中,要引入其他包中的模块,就需要通过在 os.path 中添加路径来实现:

?
现在执行文件是 bin 目录下的 bin.py,在 bin.py 中要导入 util包 中的 a模块 和 b模块,为了保证通用性,可以使用如下方式获取 log 路径,并且添加到os.path中:

import sys, os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from util import a

__name__变量

__name__ 与 __file__一样,是一个内置变量,这个变量记录了当前文件(使用 __name__ 变量的文件)是作为模块运行还是主执行文件~
示例:
a.py 文件内容

print(__name__)

# 直接执行 a.py 文件,输出:
# __main__

?
现在 在b.py文件中 import a。b.py 文件内容如下:

import a

# 现在运行 b.py 文件(这个过程会运行 a.py 文件),输出内容:
# a       ## 即 a 的模块名称

这个功能经常被用于代码的调试:

if __name__==‘__main__‘:
    pass

可以将调试的代码写在 if 语句中,用于调试当前py文件中的代码,因为直接运行当前文件, __name__ 变量的值就是 __main__。当外部模块调用的时候,就不会执行 if 语句中的内容,因为 外部模块调用 __name__ 变量的值 为模块名称~
.................^_^

原文地址:http://blog.51cto.com/ljbaby/2337278

时间: 2024-08-02 14:54:30

python模块与包的调用的相关文章

Python中函数、类、模块和包的调用

初学python阶段,大多数人对函数.类.模块和包的调用都搞得不是很清楚,这篇随笔就简单的进行说明. ?(1)函数 当函数定义好之后,可以直接调用. 比如:def summ(add1,add2),那么可以直接调用,即:summ(1,2) (2) 类 类定义好之后,不能像函数一样直接调用,而需要间接调用. 比如:class people,那么调用时,a=people(对象),之后,a.age()等等 (3) 模块 将多个类放在同一个py下,比如放在model.py中,则import model即可

Python/模块与包之模块

Python/模块与包之模块 1.什么是模块? 模块就是py文件 2.为什么要用模块? 如果在解释器上进行编码,把解释器关闭之前写的文件就不存在了,如果使用模块的话就能永久保存在磁盘中. 3.如何使用模块? 3.1 import    通过import导入要使用的模块 1 #spam.py 2 print('from the spam.py') 3 4 money=1000 5 6 def read1(): 7 print('spam->read1->money',1000) 8 9 def

Day 28(06/28)模块与包的调用

模块与包的调用 模块(modue)的概念 在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护. 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式.在Python中,一个.py文件就称之为一个模块(Module). 使用模块有什么好处? 最大的好处是大大提高了代码的可维护性. 其次,编写代码不必从零开始.当一个模块编写完毕,就可以被其他地方引用.我们在编写程序的时候,

简述Python模块和包

我们常常会使用别人写的包,假如我们使用的是Python3.4版本,安装在windows的C盘根目录下,那么外部的包一般放在:C:\Python34\Lib\sit-packages下,此目录下有以.py单独存在的文件,也有以文件夹存在的包,下面我们简单说一下Python中的模块和包,看完之后,也许会对这个目录看的更清楚一些. 一.模块 我们编写文件:a.py,放在C:\Python34\Lib\sit-packages下,里面写上一句代码为: print('this is a') 之后我们就可以

Python/模块与包之包

Python/模块与包之包 1. 包是一种通过使用模块名 来组织Python模块名称空间的方式,一个类似于目录并存有__init__.py文件的被称为包 包的本质就是一个包含__init__.py文件的目录.包A和包B下有同名模块也不会冲突,如A.a与B.a来自俩个命名空间 无论是import形式还是from...import形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警觉:这是关于包才有的导入语法 包 通常包总是一个目录,可以使用import导入包,或者from + i

python模块与包

模块是包括python定义和声明的文件.文件名=模块名+".py".模块名保存在全局变量__name__中. 1.模块中的执行语句,只是在导入时执行一次.这些语句通常用于初始化模块. 2.被导入的模块被放到全局语义表中. 3.import用法 +import moduleName +from moduleName import moudleContent +from moudleName import * 导入所有的除了以下划线开头的命名. 4.导入module查找路径:先从当前目录中

python 模块,包,变量的调用方法

#模块用来组织函数的 #包是用来组织模块的 #判断是否为包,主要是看是否有_init_.py #bin与bao有什么关系 #调用模块或者包的方法一览 # import time,sys 系统模块可以直接调用,用“,”分割 # import calculte 调用同文件夹的模块,使用方法calculte.add(1,8),add为变量或者方法 #from calculte import add,sub,这个方法可以直接使用add(),避免变量重复. #from calculte import *,

Python 模块与包

1.模块 1.在 Python 中,一个.py文件就称之为一个模块(Module). 2.大大提高了代码的可维护性. 3.编写代码不必从零开始.当一个模块编写完毕,就可以被其他地方引用 2.包 *如果不同的人编写的模块名相同怎么办?为了避免模块名冲突,Python 又引入了按目录来组织模块的方法,称为包(Package) *创建包的步骤: (1)创建一目录为包名; (2)在该文件夹下创建__init__.py文件存放包的信息,该文件可以为空; (3)根据需要存放脚本文件,已编译的扩展及子包; *

python模块与包的导入

1. 模块与包的区别 模块,即module,一个包含python语句的.py文件就是一个模块!每个源代码文件都会自动成为模块!没有额外的语法用来声明模块. 包,又称模块包,即module package,是一个目录,该目录中包含.py文件,其中必须有一个__init__.py文件,该文件用于声明和初始化模块包.第一次在进程中导入某个目录(包)时,python会自动运行__init__.py文件中的代码.该目录会在内存中创建一个模块对象,__init__.py中赋值的变量则会变成该模块对象的属性.