原文: http://zetcode.com/lang/python/modules/

在 Python 教程的这一部分中,我们将使用 Python 模块。 几个示例说明了如何创建和使用 Python 模块。

模块是一个包含 Python 代码的文件。 Python 模块具有.py扩展名。

可以使用以下方法管理 Python 代码:

  • 函数
  • 模组
  • 包装

Python 模块用于组织 Python 代码。 例如,与数据库相关的代码位于数据库模块内部,安全代码位于安全模块中,等等。较小的 Python 脚本可以具有一个模块。 但是较大的程序分为几个模块。 模块组合在一起形成包装。

Python 模块名称

模块名称是带有.py扩展名的文件名。 当我们有一个名为empty.py的文件时,模块名称为空。 __name__是一个变量,其中包含要引用的模块的名称。 当前模块,正在执行的模块(也称为主模块)有一个特殊名称:'__main__'。 使用此名称,可以从 Python 代码中引用它。

当前工作目录中有两个文件:empty.pytest_empty.py。 第二个模块是执行的主模块。 导入第一个模块。 使用import关键字导入模块。

empty.py

  1. """
  2. An empty module
  3. """

这是empty.py模块。

test_empty.py

  1. #!/usr/bin/env python
  2. import empty
  3. import sys
  4. print(__name__)
  5. print(empty.__name__)
  6. print(sys.__name__)

在此代码示例中,我们导入两个模块:内置模块sys和一个自定义模块empty。 我们将模块的名称打印到控制台。

  1. $ ./test_empty.py
  2. __main__
  3. empty
  4. sys

正在执行的模块的名称始终为'__main__'。 其他模块以文件名命名。 可以使用import关键字将模块导入其他模块。

Python 定位模块

导入模块时,解释器首先搜索具有该名称的内置模块。 如果找不到,它将在变量sys.path给定的目录列表中搜索。 sys.path是一个字符串列表,用于指定模块的搜索路径。 它由当前工作目录,在PYTHONPATH环境变量中指定的目录名称以及一些其他与安装有关的目录组成。 如果找不到该模块,则会引发ImportError

locating_modules.py

  1. #!/usr/bin/env python
  2. import sys
  3. import textwrap
  4. sp = sorted(sys.path)
  5. dnames = ', '.join(sp)
  6. print(textwrap.fill(dnames))

该脚本从sys.path变量打印所有目录。

  1. import textwrap

textwrap模块用于轻松设置段落格式。

  1. sp = sorted(sys.path)

我们从sys.path变量中检索目录列表并对它们进行排序。

  1. dnames = ', '.join(sp)

我们从列表中取出一个字符串。

  1. $ ./locating_modules.py
  2. /home/janbodnar/.local/lib/python3.5/site-packages,
  3. /home/janbodnar/PycharmProjects/Simple,
  4. /home/janbodnar/PycharmProjects/Simple, /usr/lib/python3.5,
  5. /usr/lib/python3.5/lib-dynload, /usr/lib/python3.5/plat-x86_64-linux-
  6. gnu, /usr/lib/python3/dist-packages, /usr/lib/python35.zip,
  7. /usr/local/lib/python3.5/dist-packages

这是一个示例输出。

Python import关键字

import关键字可以以多种方式使用。

  1. from module import *

此构造会将所有 Python 定义导入另一个模块的名称空间。 有一个例外。 不导入以下划线字符_开头的对象。 预期它们只能由导入的模块在内部使用。 不建议使用这种方式导入模块。

everything.py

  1. #!/usr/bin/python
  2. from math import *
  3. print(cos(3))
  4. print(pi)

此导入构造已从内置math模块导入了所有定义。 我们可以直接调用数学函数,而无需引用math模块。

  1. $ ./everything.py
  2. -0.9899924966004454
  3. 3.141592653589793

使用此导入构造可能会导致名称空间污染。 我们可能有多个同名的对象,并且它们的定义可以被覆盖。

pollution.py

  1. #!/usr/bin/env python
  2. from math import *
  3. pi = 3.14
  4. print(cos(3))
  5. print(pi)

该示例将在控制台上打印 3.14。 这可能不是我们想要的。 在大型项目中,命名空间污染可能变得至关重要。

未导入的 Python 对象

以下示例显示了未使用此import构造导入的定义。

names.py

  1. #!/usr/bin/env python
  2. """
  3. names is a test module
  4. """
  5. _version = 1.0
  6. names = ["Paul", "Frank", "Jessica", "Thomas", "Katherine"]
  7. def show_names():
  8. for i in names:
  9. print(i)
  10. def _show_version():
  11. print(_version)

这是names.py模块。

test_names.py

  1. #!/usr/bin/env python
  2. from names import *
  3. print(locals())
  4. show_names()

_version变量和_show_version()函数未导入到test_names模块中。 我们在命名空间中看不到它们。 locals()函数为我们提供了模块中所有可用的定义。

导入特定对象

使用fromimport关键字,可以仅导入某些对象。

  1. from module import fun, var

此导入构造仅从模块导入特定对象。 这样,我们仅导入我们需要的定义。

import_specific.py

  1. #!/usr/bin/python
  2. from math import sin, pi
  3. print(sin(3))
  4. print(pi)

我们从math模块导入两个对象。 我们无法引用其他定义(例如cos函数)。

imnames.py

  1. #!/usr/bin/python
  2. from names import _version, _show_version
  3. print(_version)
  4. _show_version()

我们也可以导入下划线开头的定义。 但这是一个不好的做法。

  1. $ ./imnames.py
  2. 1.0
  3. 1.0

Python 导入模块

最后一种构造使用最广泛。

  1. import module

它防止名称空间污染,并允许从模块访问所有定义。

impmod.py

  1. #!/usr/bin/env python
  2. import math
  3. pi = 3.14
  4. print(math.cos(3))
  5. print(math.pi)
  6. print(math.sin(3))
  7. print(pi)

在这种情况下,我们通过模块名称引用定义。 如我们所见,我们可以使用两个pi变量。 我们的定义来自math模块。

  1. $ ./impmod.py
  2. -0.9899924966004454
  3. 3.141592653589793
  4. 0.1411200080598672
  5. 3.14

Python 别名模块

我们可以使用as关键字为模块创建别名。

importas.py

  1. #!/usr/bin/python
  2. # importas.py
  3. import math as m
  4. print(m.pi)
  5. print(m.cos(3))

我们可以更改引用模块的名称。 为此,我们使用as关键字。

  1. $ ./importas.py
  2. 3.14159265359
  3. -0.9899924966

ImportError

如果无法导入模块,则会引发ImportError

importerror.py

  1. #!/usr/bin/env python
  2. try:
  3. import empty2
  4. except ImportError as e:
  5. print('Failed to import:', e)

我们尚未创建empty2模块。 因此引发了异常。

  1. $ ./importerror.py
  2. Failed to import: No module named empty2

示例输出。

执行 Python 模块

模块可以导入其他模块,也可以执行。 模块作者经常创建测试套件来测试模块。 仅当模块作为脚本执行时,__name__属性等于'__main__'

我们将在斐波那契模块上对此进行演示。 斐波那契数是一个数字序列,其中每个数字都是其两个直接前辈的总和。

fibonacci.py

  1. #!/usr/bin/env python
  2. """
  3. A module containing the fibonacci
  4. function.
  5. """
  6. def fib(n):
  7. a, b = 0, 1
  8. while b < n:
  9. print(b, end=" ")
  10. (a, b) = (b, a + b)
  11. # testing
  12. if __name__ == '__main__':
  13. fib(500)

通常可以照常导入该模块。 该模块也可以执行。

  1. $ ./fibonacci.py
  2. 1 1 2 3 5 8 13 21 34 55 89 144 233 377

如果确实导入了fibonacci模块,则不会自动执行测试。

  1. >>> import fibonacci as fib
  2. >>> fib.fib(500)
  3. 1 1 2 3 5 8 13 21 34 55 89 144 233 377

导入了fibonacci模块,并执行了fib()函数。

Python dir函数

内置的dir()函数提供了包含模块定义名称的字符串排序列表。

dirfun.py

  1. #!/usr/bin/env python
  2. """
  3. This is dirfun module
  4. """
  5. import math, sys
  6. version = 1.0
  7. names = ["Paul", "Frank", "Jessica", "Thomas", "Katherine"]
  8. def show_names():
  9. for i in names:
  10. print(i)
  11. print(dir())

在此模块中,我们导入两个系统模块。 我们定义一个变量,一个列表和一个函数。

  1. print(dir())

dir()函数返回模块当前名称空间中所有可用的名称。

  1. $ ./dirfun.py
  2. ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__',
  3. '__package__', '__spec__', 'math', 'names', 'show_names', 'sys', 'version']

我们可以看到一些内置名称,例如'__file__''__name__',以及我们定义和导入的所有其他名称。

Python 全局函数

globals()函数返回代表当前全局名称空间的字典。 它是全局名称及其值的字典。 它是当前模块的字典。

globalsfun.py

  1. #!/usr/bin/env python
  2. import textwrap
  3. version = 1.0
  4. def myfun():
  5. pass
  6. gl = globals()
  7. gnames = ', '.join(gl)
  8. print(textwrap.fill(gnames))

我们使用globals()函数来打印当前模块的所有全局名称。

  1. $ ./globalsfun.py
  2. textwrap, __package__, version, __builtins__, __name__, __spec__,
  3. __doc__, gl, __cached__, myfun, __loader__, __file__

这些是当前模块的全局名称。

Python __module__属性

__module__类属性具有定义该类的模块的名称。

animals.py

  1. """
  2. module animals
  3. """
  4. class Cat:
  5. pass
  6. class Dog:
  7. pass

这是animals.py文件的内容。 我们有两个类。

mclass.py

  1. #!/usr/bin/env python
  2. from animals import Cat
  3. class Being:
  4. pass
  5. b = Being()
  6. print(b.__module__)
  7. c = Cat()
  8. print(c.__module__)

在此代码中,我们使用__module__属性。

  1. from animals import Cat

animals模块,我们导入Cat类。

  1. class Being:
  2. pass

在当前模块中,我们定义一个类Being

  1. b = Being()
  2. print(b.__module__)

创建Being类的实例。 我们打印其模块的名称。

  1. c = Cat()
  2. print(c.__module__)

我们从Cat类创建一个对象。 我们还将在定义模块的位置打印。

  1. $ ./mclass.py
  2. __main__
  3. animals

当前模块的名称为'__main__'Cat's模块的名称是动物。

本章是关于 Python 中的模块的。