第十四章 Python_模块和包

模块化编程

简介

Python 有时候称为胶水语言,就是因为它有强大的可扩展性,这个扩展性就是用模块实现的。

模块其实就是一个以 .py 结尾的 Python 文件,这个文件中可以包含变量、函数、类等。

这个模块可以包含实现了一个或者多个功能的代码。

模块可以在其他 Python 文件中使用,可以通过网络进行传播。

这样的话,如果想在你的程序中实现某些功能,其实网络的其他程序猿已经给你写好了,下载下来,安装到自己的环境下,就可以使用了。

模块化编程

模块化编程是指将大型,笨拙的编程任务分解为单独的,更小的,更易于管理的子任务或模块的过程。然后可以像构建块一样拼凑单个模块以创建更大的应用程序。

在大型应用程序中模块化代码有几个优点:

  • 简单性:模块通常只关注问题的一小部分,而不是关注当前的整个问题。如果您正在处理单个模块,那么您的头脑中要思考的将有一个较小的问题范围。这使得开发更容易,更不容易出错。
  • 可维护性:模块通常设计为能够在不同的问题域之间实施逻辑边界。如果以最小化相互依赖性的方式编写模块,则对单个模块的修改将对程序的其他部分产生影响的可能性降低。(您甚至可以在不了解该模块之外的应用程序的情况下对模块进行更改。)这使得许多程序员团队在大型应用程序上协同工作更加可行。
  • 可重用性:单个模块中定义的功能可以通过应用程序的其他部分轻松地重用。这消除了重新创建重复代码的需要。
  • 范围:模块通常定义一个单独的命名空间,这有助于避免程序的不同区域中的变量名之间的冲突。

一、模块分类

实现方式分类

实际上有两种不同的方法可以在Python中定义模块

  1. 模块可以用Python本身编写。
  2. 模块可以用C编写并在运行时动态加载,就像re正则表达式)模块一样。
  3. 一个内置的模块,本质上已经包含在了 Python 解释器中,像itertools模块

以上情况下,模块的内容都以相同的方式访问:使用import语句

在这里,重点将主要放在用Python编写的模块上。用Python编写的模块的妙处在于它们的构建极其简单。您需要做的就是创建一个包含合法Python代码的文件,然后为该文件命名并带有 .py 扩展名即可。

归属分类

模块还可以分为

  • 内置模块 ,就是 python 解释器中自带的. 如: os re itertools

  • 第三方模块, 这些模块需要自己安装,就像是在 Linux 系统中安装软件一样。

  • 自定义模块, 这个就是自己编写的模块。

二、模块的安装

安装方法

1. pip3 工具安装

例如下面的示例是安装用于执行远程主机命令的模块 paramiko

注意: pip3 是 bash 环境下的命令

$ pip3 install paramiko

python2.x 使用 pip
python3.x 使用 pip3
当然这也不是固定的,比如你给 pip3 定义了一个别名 pip

2. 源码安装

源码安装就是,从网络上下载没有封装的 python 文件的源码,之后在本地执行其源码中的 setup.py 文件进行安装。

模块的源码一般都有一个主目录,主目录中包含了一个到多个子目录和文件。
但是主目录下一定有一个 setup.py 的文件,这个是源码安装的入口文件,就是需要执行这个文件并且传入一个 install 参数进行源码安装。

示例:

a. 下载源码包

wget https://files.pythonhosted.org/packages/4a/1b/9b40393630954b54a4182ca65a9cf80b41803108fcae435ffd6af57af5ae/redis-3.0.1.tar.gz

b. 解压源码包

tar -xf redis-3.0.1.tar.gz

  1. 进入模块源码的主目录,并安装源码包
image
image

上面表示安装成功

三、自定义模块

有的情况下,是需要自己编写一些模块的,这种就是自定义模块了。

示例:

some_mod.py

x = 10

li = ['shark', 18]

def foo():
    return 30

class Person():
    def __init__(self, name, age):
        self.name = name
        self.age = age

四、模块的使用

使用模块需要先导入模块名。

模块名就是把 .py 去掉后的文件名。比如 some_mod.py 的模块名就是 some_mod

1. 导入模块

import  some_mod

2. 使用模块中的对象

要想使用模块中的变量名或者函数名等,只需要使用 模块名.变量名 的方式即可。

例如,下面是使用的了 some_mod 模块中的 foo 函数。

import  some_mod

some_mod.foo()

3. 更多模块导入的方式

a. 从模块中导入其中的一个对象

from some_mod  import  x

b. 从模块中导入多个对象

from some_mod import x, foo

c. 从模块中导入全部的对象, 不建议这么做, 应该视使用模块中的对象的情况而定

from some_mod import *

导入模块时模块的代码会自动被执行一次,在一个程序中多次导入同一个模块,此模块的代码仅会运行一次。

[root@kube-master py3]# cat some_mod.py
print("hello shark")
[root@kube-master py3]# cat t.py
import some_mod
import some_mod
[root@kube-master py3]# python t.py
hello shark

二、包

包就是包含了一个 __init__.py 文件的文件夹,这个文件夹下可以有更多的目录或文件。就是说,包里可以用子包或单个 .py 的文件。

其实包也是模块,就是说包和单一的 .py 文件统称为模块。

包的目录结构

image

文件 __init__.py

__init__.py 文件,在 Python3.x 中可以没有,但是在 Python2.x 中必须有。

文件中可以有代码,也可以是个空文件,但是文件名不能是其他的。

到导入包的时候,此文件假如存在,会以此文件去见包的名称空间。

也就是说,导入如包的时候,只要在 __init__.py 文件中的名称才可以生效。否则,即使是一个模块在包目录下面也不会被导入到内存中,也就不会生效。

使用包

示例包目录机构

image

使用包也需要导入

a. 单独导入包

import package  # 注意这样不会导入其下面的模块和子包

b. 从包中导入下面的模块

from package import t

c. 从包中导入下面的子包,注意这不会导入子包下面的任何模块

from package import subpkg

d. 从包的子包中导入子包的模块

from package.subpkg import som_mod

e. 从包或子包的模块中导入具体的对象

from package.t  import foo

from package.subpkg.som_mod import x

from package.t  import x  as y   # 把 x 导入后起个别名 y

记住一点:不论是导入包还是模块,从左向右的顺序来说,最后一个点儿的左边一定是一个包名,而不能是一个模块名

下面是错误的

import package.t.foo
from package.subpkg import som_mod.x

三模块的内置变量 __name__

每个 .py 文件都有一个变量名 __name__, 这个变量名的值会根据这个文件的用途不同而随之变化。

  1. 当文件作为模块被其他文件使用时,__name__ 的值是这个文件的模块名

  2. 当文件作为脚本(就是作为可执行文件)使用时,__name__ 的值是字符串类型的 '__main__'

通常你会看到一些 Python 脚本中会有类似下面的代码:

some_script.py

def foo():
    pass

def func():
    pass

def main():
    foo()
    func()

if __name__ == '__main__':
       main()

使用这个脚本

python3 some_script.py

这样执行这个脚本的话,其内置的 __name__ 变量的值就是字符串的 '__main__'
这样的话, if 的判断添加就会达成,从而其语句下面的代码就会执行, main() 函数就会被调用 。

模块名包名的搜索路径(扩展)

这个就像是在 Linux 系统中,当执行一个命令时候,系统会查找这个命令的二进制文件一样。Linux 系统是从环境变量 PATH 中查找。

查找顺序

当你导入模块或者包的时候, 查找模块或包的顺序:

  1. 系统会从内存中查找,看是否之前已经导入过此模块。

  2. 假如第一次导入,内存中就不会存在,这时再从当前目录下查找。

  3. 最再从sys.path 输出的值中的路径里查找模块名或者包名。

都找不到,就会报错,并且整个程序会退出

image
import sys

print(sys.path)

sys.path 输出的值是一个 Python 的列表,这个列表我们可以对其修改的。

比如我们可以把某个文件的路径添加到此列表中,通常会这么做。

run.py

import os,sys

BASE_DIR = os.path.dirname(os.path.abspath(__file__))

sys.path.insert(0, BASE_DIR)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容