首先这四个概念要分成两组

  1. 模块(module)和包(package)是一组,在python中是有明确的含义的,而且和其他语言有略微的差异。
  2. 库(library)和框架(framework)另一组,是编程中比较通用的概念,经常=拿来比较。

先来说模块(module)和包(package)

其关系如下图所示:

python中包和模块的关系 python 库,包,模块的区别_python中包和模块的关系

 

这两个概念并不是大家所想的module就是py文件,package就是带__init__的文件夹。这个说法目前已经有些过时了。 先看看官方文档怎么说的吧:

module

An object that serves as an organizational unit of Python code. Modules have a namespace containing arbitrary Python objects. Modules are loaded into Python by the process of importing.

package

A Python module which can contain submodules or recursively, subpackages. Technically, a package is a Python module with an __path__ attribute.

也就是说,模块(module)就是有命名空间的,python代码的一种组织形式。不一定是py文件,可以是.so,甚至可以是目录。 而包(package)是一种可包含子模块或递归地包含子包的模块(module)。所以说包(package)也是一种模块(module)。 辨别到底是模块(module)还是包(package),就看这个模块(module)是否含有__path__的属性。

比如我们经常使用的re和json模块,可以看出,python对他们的定义都是module,json包含__path__ 而re没有。

>>> import re
>>> re
<module 're' from '/Users/xxx/anaconda3/lib/python3.7/re.py'>
>>> re.__path__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 're' has no attribute '__path__'

>>> import json
>>> json
<module 'json' from '/Users/xxx/anaconda3/lib/python3.7/json/__init__.py'>
>>> json.__path__
['/Users/xxx/anaconda3/lib/python3.7/json']

再说__init__.py的问题,在python3.3之后,PEP-420将包(package)分为了两种,一种是之前包含__init__.py的包,叫regular package。如果不包含__init__.py,python认为这个目录是namespace package。 也就是说 __init__.py不再是包(package)的必需品。 比如我建立如下目录

> tree
some_path
├── namespace_pkg     # no __init__.py, regular package
│   └── say.py
└── regular_pkg 
    ├── __init__.py   # has __init__.py, namespace package
    └── say.py

其用法几乎一摸一样。

>>> import namespace_pkg
>>> namespace_pkg
<module 'namespace_pkg' (namespace)>
>>> import regular_pkg
>>> regular_pkg
<module 'regular_pkg' from '/some_path/regular_pkg/__init__.py'>
>>> import namespace_pkg.say
>>> namespace_pkg.say.hello()
Hello, This is Namespace Package!
>>> import regular_pkg.say
>>> regular_pkg.say.hello()
Hello, This is Regular Package!

虽然__init__.py不再是必需的,但是它让你有更多组织模块的机会,目前使用__init__.py还是主流。

再来说库(library)和框架(framework)

库(library)其实主要用来表示可重复利用的代码。别人写好了,拿过来白嫖一下,我自己也可以写个自定义的库(library)。不管是复杂还是简单,只要是一个可重复使用的代码,都可以称为库(library)。比如大家常用的re,json,numpy,pandas。

其工作模式大概是下面左边这样的:

python中包和模块的关系 python 库,包,模块的区别_python中包和模块的关系_02

 

上面的模式中,是你调用库(library)来写程序,整体的流程,结构,标准都是你说了算。而框架(framework),则反过来,是框架(framework)在"调用"你。整体的流程,结构和标准你一般是不会改的,你所做的都是依赖于框架,在上面添砖加瓦。比如Django,Flask。

大致的流程是上图右边那样的。