老男人开始学python之什么是模块、包、库?

在上一篇《老男人开始学python之Flask中的“Hello World”》中,虽然只按照教程写了几行短短的代码,但是对于初学者的我来说就产生了一些疑问,有一些不明白的地方?

  1. 为什么文件名是“__init__.py”?
  2. __name__”是什么?
  3. from ... import ... 是什么意思?
  4. form ... import ... 和 import ...的区别是什么?

带着问题去看了Python基础教程模块一节记录总结一下。
参考教程:
廖雪峰:模块、使用模块、安装第三方模块
链接:http://www.liaoxuefeng.com/

一、什么是模块、包、库?

| Module(模块)| Package(包)| Library(库)|
| --------------------- | :------------------ | --------------- -: |
| 一个.py文件就称之为一个模块(Module)| 只要包含__init__.py文件的文件夹就叫做包| 参考其他编程语言的说法。就是指Python中完成一定功能的代码集合,供用户使用的代码组合。在python中是包和模块的形式 | | abc.py模块名就是abc;|1.init.py文件必须存在,否则就是一个文件夹;2.init.py文件可以为空,也可以有python代码;3. 可以有多级层次结构包含多个模块或子包组成;4.init.py`文件本身就是一个模块,模块名就是包含它的文件夹的名称; |例如常说的第三方库,是否可以简单理解为包含多个Package(包)完成某功能的一个代码集合 |

1.Package 包中都可以包含什么?

F:\pythontest\test2.py             # test2模块
F:\pythontest\test3                # test3文件夹中包含__init__.py文件,因此是一个包;
│  a.py                            # test3.a模块;
│  b.py                            # test3.b模块; 
│  __init__.py                     # 也是一个模块,名称是:test3
│
├─b                                # 包含2个模块的一个【文件夹】,但是名称和test3.b名称同名了,该【文件夹】下的模块能正常使用吗?如果这里是个同名的子包呢?
│      a.py
│      b.py
│
├─c                                # 一个空【文件夹】
├─d                                # 因为包含__init__.py文件,因此是一个子包                 
│      a.py                        # 模块名:test3.d.a
│      b.py                        # 模块名:test3.d.a
│      __init__.py                 # 模块名:test3.d  
│
└─e                                # 包含2个模块的一个【文件夹】,该文件夹下的2个模块能用吗?
        a.py                       # 暂认为模块名为:test3.e.a
        b.py                       # 暂认为模块名为:test3.e.b

如上所示,一个包中可以包含:模块(a、b)、包含模块的文件夹(b、e)、空文件夹(c)、子包(d)。

【说明】到了这里解决了第1个问题,为什么文件名是“__init__.py”,因为它是一个Package(包);

下边做一些测试:

#F:\pythontest\test3\a.py代码如下:
def a():
    return "my name is 'a'"
#F:\pythontest\test3\b.py代码如下:
def b():
    return "my name is 'b'"
#F:\pythontest\test3\b\a.py代码如下:
def a():
    return "我是B文件夹下的 'a'"
#F:\pythontest\test3\b\b.py代码如下:
def b():
    return "我是B文件夹下的 'b'"
#F:\pythontest\test3\d\a.py代码如下:
def a():
    return "我是D子包中的 'a'"
#F:\pythontest\test3\d\b.py代码如下:
def b():
    return "我是D子包中的 'b'"

__init__.py 文件全部为空,F:\pythontest\test2.py文件中代码分别为如下几种情况的执行结果:

-----------------------------------------------------------------------------------
import test3
x = test3.a.a()
print (x)


#执行结果:
F:\pythontest>flask\Scripts\python.exe test2.py
Traceback (most recent call last):
  File "test2.py", line 2, in <module>
    x = test3.a.a()
AttributeError: 'module' object has no attribute 'a'

【总结】:因为导入的模块名为test3,也就是test3文件夹下的`__init__.py `文件,而该文件为空,所以找不到test3.a模块中的a函数;

-----------------------------------------------------------------------------------

使用import test3.a 导入test3.a模块,即test3文件夹下的a.py文件,就可以正常执行:

import test3.a
x = test3.a.a()
print (x)

#执行结果:
F:\pythontest>flask\Scripts\python.exe test2.py
my name is 'a'

-----------------------------------------------------------------------------------
#代码如下:
import test3.b
x = test3.b.b()
print (x)
#执行结果:
F:\pythontest>flask\Scripts\python.exe test2.py
my name is 'b'

#代码更改如下:测试导入b文件夹中的b模块
import test3.b.b
x = test3.b.b.b()
print (x)

#执行结果:没有模块test3.b.b,test3.b不是一个包;
F:\pythontest>flask\Scripts\python.exe test2.py
Traceback (most recent call last):
  File "<frozen importlib._bootstrap>", line 2218, in _find_and_load_unlocked
AttributeError: 'module' object has no attribute '__path__'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "test2.py", line 1, in <module>
    import test3.b.b
ImportError: No module named 'test3.b.b'; 'test3.b' is not a package

-----------------------------------------------------------------------------------
如果给b文件夹下放一个空__init__.py文件,这时候b文件夹就成了test3的一个子包则:
import test3.b
x = test3.b.b()
print (x)

#执行结果:
F:\pythontest>flask\Scripts\python.exe test2.py
Traceback (most recent call last):
  File "test2.py", line 2, in <module>
    x = test3.b.b()
AttributeError: 'module' object has no attribute 'b'

【总结】因为导入test3.b模块的时候实际上b子包把test3.b模块覆盖了,实际上导入的是b文件夹中的__init__.py文件,而该文件为空,因此找不到b函数;

#更改代码如下:导入test3.b模块,即test3\b\__init__.py
import test3.b
x = test3.b.a.a()
print (x)

#同时修改test3\b\__init__.py文件代码如下:
import test3.b.a
#执行结果:
F:\pythontest>flask\Scripts\python.exe test2.py
我是B文件夹下的 'a'

这个时候就是test3\b\__init__.py文件中导入了test3.b.a模块,然后在test2.py文件中导入了test3.b模块即test3\b\__init__.py文件,换句话说就是在test3\b\__init__.py文件中引入了test3\b\a.py文件,然后在test2.py文件中又引入了test3\b\__init__.py文件,因此a.py中的a函数能被正常执行。

-----------------------------------------------------------------------------------
#最后来看看e文件夹中的模块文件能否被正常导入并使用模块中的函数?
代码如下:
import test3.e.a
x = test3.e.a.a()
print (x)

#执行结果:
F:\pythontest>flask\Scripts\python.exe test2.py
我是E文件夹下的 'a'模块

从执行结果来看,是可以正常运行的。

更改一下代码:
import test3.e
x = test3.e.a.a()
print (x)
执行结果:
F:\pythontest>flask\Scripts\python.exe test2.py
Traceback (most recent call last):
  File "test2.py", line 2, in <module>
    x = test3.e.a.a()
AttributeError: 'module' object has no attribute 'a'

从以上两例测试,可以看到虽然e只是个文件夹不是子包,但是该文件夹下的模块文件依然可以被导入。

上边的两个问题:

  1. 含2个模块的一个【文件夹】,但是名称和test3.b名称同名了,该【文件夹】下的模块能正常使用吗?如果这里是个同名的子包呢?

    如果在test3包中,含有一个b.py和一个b文件夹,则b.py文件(模块)可以被导入,而b文件夹中的.py文件不能被导入;
    如果b文件夹是一个子包,则子包覆盖b.py;
    【注意】不要重名,以免混淆!

  2. 文件夹e,不是子包,该文件下包含2个.py文件(模块),该文件夹下的2个模块能用吗?

    可以被导入使用。这是为什么呢?

二、如何使用Module(模块)?

import 命令为导入Module(模块)命令,而Module指的就是一个.py文件,其实就可以认为是在一个.py文件中引入另外一个.py文件。

1. 使用导入Module(模块)命令import

有几种格式:

命令 解释
import module 导入单个模块
import module as name 导入单个模块并重命名
import moudule1, moudule2,module3,... 一次导入多个模块
import moudule1 as name1,module2 as name2,... 一次导入多个模块并重命名

一般在文件首部导入所有模块,推荐顺序如下:

python标准库
第三方模块
应用程序自定义模块

2. 使用from...import...语句导入模块的属性(变量、函数、对象)

命令 解释
from module import name1,name2,name3 单行导入
from module import name1,name2,\ name3 多行导入
from module import * 导入全部属性,一般不推荐使用,适合模块中变量名很长和很多的情况。容易覆盖当前命名空间中现有的名字

当试图加载一个模块的时候,Python会在指定的路径下搜索对应的.py文件,如果找不到,就会报错。

默认情况下,Python解释器会搜索当前文件夹、所有已安装的内置模块和第三方模块,搜索路径存放在sys模块的path变量中。

有两种方法修改搜索路径:
一是直接修改sys.path,添加要搜索的文件夹:sys.path.append('路径')

第二种方法是设置环境变量PYTHONPATH,该环境变量的内容会被自动添加到模块搜索路径中。设置方式与设置Path环境变量类似。注意只需要添加你自己的搜索路径,Python自己本身的搜索路径不受影响。

模块被导入时,加载的时候模块顶层代码会被执行,一个模块无论被导入多少次,只加载一次,可以防止多次导入时代码被多次执行。

内建函数reload可以重新导入一个已经存在的模块。

三、 “__name__”是什么?

简单的说:
1.如果模块(就是一个.py)文件是直接执行的,则__name__值就等于__main__
2.如果模块是被导入的时候,__name__的值就是模块名;

#test_name2.py 代码为:
def test_name2():                                # 定义一个函数test_name2
    b = __name__                                 # 将__name__赋值给变量b
    return b                                     # 函数返回变量b的值
if __name__ == "__main__":                       # 如果__name__ 等于字符串__main__ 就可以认为是直接执行的test_name2.py文件,则打印test_name2()函数的返回值;
    print (test_name2())

#test_name1.py 代码为:

import test_name2                                # 导入模块 test_name2
print (test_name2.test_name2())                  # 打印test_name2模块中的test_name2函数值;

直接执行test_name2的结果:结果为__main__
F:\pythontest>flask\Scripts\python.exe test_name2.py
__main__

直接执行test_name1的结果:结果为模块名
F:\pythontest>flask\Scripts\python.exe test_name1.py
test_name2

可做调试代码用;
参考:
python:浅析python 中name = 'main' 的作用
python中name的使用

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

推荐阅读更多精彩内容