Python3 Модуль
В предыдущих главах мы в основном использовали интерпретатор Python для программирования. Если вы выйдете из интерпретатора Python и войдете снова, все определённые вами методы и переменные исчезнут.
Чтобы решить это, Python предоставляет способ хранить эти определения в файле для использования скриптами или экземплярами интерактивного интерпретатора. Этот файл называется модулем.
Модуль в Python — это файл, содержащий определения и инструкции Python. Имя файла — это имя модуля плюс суффикс.py.
Модуль может содержать функции, классы, переменные и исполняемый код. С помощью модулей мы можем организовывать код в повторно используемые единицы для упрощения управления и поддержки.
Роль модулей
Повторное использование кода: Инкапсулируйте общую функциональность в модули, которые можно повторно использовать в нескольких программах.
Управление пространствами имён: Модули позволяют избегать конфликтов имён; функции или переменные с одинаковыми именами в разных модулях не мешают друг другу.
Организация кода: Разделите код на разные модули по функциям, что делает структуру программы понятнее.
Ниже приведён пример использования модуля из стандартной библиотеки Python.
Пример (Python 3.0+)
Результат выполнения выглядит следующим образом:
$ python using_sys.py 参数1 参数2 命令行参数如下: using_sys.py 参数1 参数2 Python 路径为: ['/root', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu', '/usr/lib/python3.4/lib-dynload', '/usr/local/lib/python3.4/dist-packages', '/usr/lib/python3/dist-packages']
- 1. import sys импортирует модуль sys.py из стандартной библиотеки Python; это способ импорта модуля.
- 2. sys.argv — это список, содержащий аргументы командной строки.
- 3. sys.path содержит список путей, по которым интерпретатор Python автоматически ищет требуемые модули.
инструкция import
Чтобы использовать исходный файл Python, просто выполните оператор import в другом исходном файле. Синтаксис следующий:
import module1[, module2[,... moduleN]
Когда интерпретатор встречает инструкцию import, модуль будет импортирован, если он находится в текущем пути поиска.
Путь поиска — это список всех каталогов, которые будет просматривать интерпретатор. Если вы хотите импортировать модуль support, нужно поместить команду в начало скрипта:
Код файла support.py
test.py импортирует модуль support:
Код файла test.py
Вывод приведенного выше примера:
$ python3 test.py Hello : Example
Скачать код
Модуль импортируется только один раз, независимо от того, сколько раз вы выполняетеimport. Это предотвращает повторное выполнение импортированного модуля.
Когда мы используем инструкцию import, как интерпретатор Python находит соответствующий файл?
Это связано с путём поиска Python. Путь поиска состоит из ряда имён каталогов, и интерпретатор Python ищет импортируемый модуль в этих каталогах по очереди.
Путь поиска модулей
При импорте модуля Python ищет модуль в следующем порядке:
Текущий каталог.
Переменная окружения
PYTHONPATHУказанный каталог.Каталог стандартной библиотеки Python.
.pthКаталог, указанный в файле.
Путь поиска определяется во время компиляции или установки Python, а установка новых библиотек также может его изменять. Путь поиска хранится в переменной path модуля sys. Давайте проведём простой эксперимент: в интерактивном интерпретаторе введите следующий код:
>>> import sys >>> sys.path ['', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu', '/usr/lib/python3.4/lib-dynload', '/usr/local/lib/python3.4/dist-packages', '/usr/lib/python3/dist-packages'] >>>
Вывод sys.path представляет собой список, где первый элемент — пустая строка '', обозначающая текущий каталог (если вывести из скрипта, можно яснее увидеть, какой это каталог), то есть каталог, в котором мы запускаем интерпретатор Python (для скриптов — каталог, где находится запускаемый скрипт).
Следовательно, если, как в моём случае, в текущем каталоге есть файл с тем же именем, что и импортируемый модуль, он затенит импортируемый модуль.
Поняв концепцию пути поиска, можно изменитьsys.path, чтобы импортировать некоторые модули, которых нет в пути поиска.
Теперь создайте файл с именем fibo.py в текущем каталоге интерпретатора или в каталоге, входящем в sys.path. Код выглядит следующим образом:
Пример
Затем войдите в интерпретатор Python и используйте следующую команду для импорта этого модуля:
>>> import fibo
Это не записывает имена функций, непосредственно определённых в fibo, в текущую таблицу символов; оно записывает туда только имя модуля fibo.
Вы можете использовать имя модуля для доступа к функциям:
Пример
Если вы планируете часто использовать функцию, вы можете присвоить ей локальное имя:
>>> fib = fibo.fib >>> fib(500) 1 1 2 3 5 8 13 21 34 55 89 144 233 377
инструкция from ... import
Инструкция from в Python позволяет импортировать указанную часть из модуля в текущее пространство имён. Синтаксис выглядит следующим образом:
from modname import name1[, name2[, ... nameN]]
Например, чтобы импортировать функцию fib из модуля fibo, используйте следующую инструкцию:
>>> from fibo import fib, fib2 >>> fib(500) 1 1 2 3 5 8 13 21 34 55 89 144 233 377
Это объявление не импортирует весь модуль fibo в текущее пространство имён; оно только вносит функцию fib из fibo.
Псевдонимы модулей
Используйтеasключевое слово для создания псевдонима модуля или функции:
import numpy as np # 将 numpy 模块别名设置为 np from math import sqrt as square_root # 将 sqrt 函数别名设置为 square_root
инструкция from ... import *
Импорт всего содержимого модуля в текущее пространство имён также возможен, просто используйте следующее объявление:
from modname import *
Это обеспечивает простой способ импорта всех элементов из модуля.
Не рекомендуется, так как это может легко привести к конфликтам имён.
Углублённое изучение модулей
Помимо определений методов, модуль может также содержать исполняемый код. Этот код обычно используется для инициализации модуля. Он выполняется только при первом импорте модуля.
Каждый модуль имеет собственную независимую символьную таблицу, которая используется как глобальная символьная таблица для всех функций внутри модуля.
Поэтому авторы модулей могут безопасно использовать эти глобальные переменные внутри модуля, не беспокоясь о том, что их спутают с глобальными переменными других пользователей.
С другой стороны, когда вы действительно знаете, что делаете, вы также можете обращаться к функциям внутри модуля, используя запись вида modname.itemname.
Модули могут импортировать другие модули. Используйте import в начале модуля (или скрипта, или в другом месте), чтобы импортировать модуль. Конечно, это всего лишь соглашение, а не обязательное требование. Имя импортированного модуля будет помещено в символьную таблицу модуля, с которым в данный момент выполняется работа.
Есть и другой способ импорта: можно использовать import, чтобы напрямую импортировать имена (функции, переменные) из модуля в текущий рабочий модуль. Например:
>>> from fibo import fib, fib2 >>> fib(500) 1 1 2 3 5 8 13 21 34 55 89 144 233 377
Этот способ импорта не помещает имя импортированного модуля в текущую символьную таблицу (так что в этом примере имя fibo не определено).
Есть ещё один способ, который может сразу импортировать все имена (функции, переменные) из модуля в символьную таблицу текущего модуля:
>>> from fibo import * >>> fib(500) 1 1 2 3 5 8 13 21 34 55 89 144 233 377
Это импортирует все имена, но имена, начинающиеся с одного подчёркивания (_), не включаются. В большинстве случаев программисты Python не используют этот способ, потому что имена, импортированные из других источников, могут переопределить существующие определения.
Атрибут __name__
Когда модуль впервые импортируется другой программой, его основная программа запускается.
If we want a certain block of code in the module not to execute when the module is imported, we can use the__name__, чтобы этот блок выполнялся только при запуске самого модуля.
#!/usr/bin/python3
# Filename: using_name.py
if __name__ == '__main__':
print('程序自身在运行')
else:
print('我来自另一模块')
Вывод во время выполнения выглядит так:
$ python using_name.py 程序自身在运行
$ python >>> import using_name 我来自另一模块 >>>
Объяснение: каждый модуль имеет атрибут __name__.
Если модуль запускается напрямую,
__name__его значение равно__main__。Если модуль импортируется,
__name__его значение — имя модуля.
Примечание:__name__и__main__Внизу есть двойные подчёркивания,_ _это чтобы убрать пробел между ними.
Функция dir()
Встроенная функция dir() может найти все имена, определённые внутри модуля. Она возвращает их в виде списка строк:
>>> import fibo, sys >>> dir(fibo) ['__name__', 'fib', 'fib2'] >>> dir(sys) ['__displayhook__', '__doc__', '__excepthook__', '__loader__', '__name__', '__package__', '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe', '_home', '_mercurial', '_xoptions', 'abiflags', 'api_version', 'argv', 'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'float_repr_style', 'getcheckinterval', 'getdefaultencoding', 'getdlopenflags', 'getfilesystemencoding', 'getobjects', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval', 'gettotalrefcount', 'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info', 'intern', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1', 'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout', 'thread_info', 'version', 'version_info', 'warnoptions']
Если аргумент не указан, функция dir() перечисляет все имена, определённые в данный момент:
>>> a = [1, 2, 3, 4, 5] >>> import fibo >>> fib = fibo.fib >>> dir() # 得到一个当前模块中定义的属性列表 ['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys'] >>> a = 5 # 建立一个新的变量 'a' >>> dir() ['__builtins__', '__doc__', '__name__', 'a', 'sys'] >>> >>> del a # 删除变量名a >>> >>> dir() ['__builtins__', '__doc__', '__name__', 'sys'] >>>
Стандартные модули
Сам Python поставляется с некоторыми стандартными библиотеками модулей, которые будут представлены в справочнике по библиотеке Python (то есть в «Library Reference» далее).
| Имя модуля | Описание |
|---|---|
math | Математические операции (такие как квадратный корень, тригонометрические функции и т. д.) |
os | Функции, связанные с операционной системой (например, операции с файлами и каталогами) |
sys | Системные параметры и функции |
random | Генерация случайных чисел |
datetime | Обработка дат и времени |
json | Обработка данных JSON |
re | Операции с регулярными выражениями |
collections | Предоставляют дополнительные структуры данных (такие как defaultdict, deque) |
itertools | Предоставляют инструменты для работы с итераторами |
functools | Инструменты для функций высшего порядка (такие как reduce, lru_cache) |
Некоторые модули встроены непосредственно в интерпретатор. Хотя они не являются встроенными возможностями самого языка, их можно использовать очень эффективно, даже для системных вызовов.
Эти компоненты настраиваются по-разному в зависимости от операционной системы. Например, модуль winreg предоставляется только в системах Windows.
Обратите внимание, что существует специальный модуль sys, который встроен в каждый интерпретатор Python. Переменные sys.ps1 и sys.ps2 определяют строки, соответствующие первичному и вторичному приглашениям:
>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>> sys.ps1 = 'C> '
C> print('Example!')
Example!
C>
Пакет
Пакеты — это способ управления пространствами имён модулей Python с использованием «точечных имён модулей».
Например, если имя модуля — A.B, то оно представляет подмодуль B в пакете A.
Так же как и при использовании модулей, вам не нужно беспокоиться о том, что глобальные переменные будут влиять друг на друга между разными модулями; использование точечных имён модулей также означает, что вам не нужно беспокоиться о модулях с одинаковыми именами в разных библиотеках.
Таким образом, разные авторы могут предоставлять модули NumPy или библиотеки графики Python.
Предположим, вы хотите разработать набор модулей (или «пакет») для единообразной обработки звуковых файлов и данных.
Существует множество различных аудиоформатов (в основном различающихся по расширениям, например: .wav, :file:.aiff, :file:.au), поэтому вам нужен постоянно растущий набор модулей для преобразования между разными форматами.
А для этих аудиоданных также существует множество различных операций (таких как микширование, добавление эха, добавление функций эквалайзера, создание искусственных стереоэффектов), поэтому вам также нужен бесконечный набор модулей для обработки этих операций.
Вот возможная структура пакета (в иерархической файловой системе):
sound/ 顶层包
__init__.py 初始化 sound 包
formats/ 文件格式转换子包
__init__.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...
effects/ 声音效果子包
__init__.py
echo.py
surround.py
reverse.py
...
filters/ filters 子包
__init__.py
equalizer.py
vocoder.py
karaoke.py
...
При импорте пакета Python ищет в каталогах из sys.path подкаталоги, содержащиеся в пакете.
Каталог распознаётся как пакет только в том случае, если он содержит файл с именем __init__.py. В основном это делается для того, чтобы некоторые чрезмерно распространённые имена (такие как string) случайно не влияли на допустимые модули в пути поиска.
В простейшем случае достаточно разместить пустой файл :file:__init__.py. Конечно, этот файл также может содержать некоторый код инициализации или присваивать значение переменной __all__ (описанной позже).
Пользователи могут импортировать из пакета только один конкретный модуль за раз, например:
import sound.effects.echo
Это импортирует подмодуль: sound.effects.echo. Обращаться к нему нужно по полному имени:
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
Есть другой способ импортировать подмодуль:
from sound.effects import echo
Это также импортирует подмодуль: echo, и он не требует тех длинных префиксов, поэтому его можно использовать так:
echo.echofilter(input, output, delay=0.7, atten=4)
Другой вариант — напрямую импортировать функцию или переменную:
from sound.effects.echo import echofilter
Аналогично этот способ импортирует подмодуль: echo, и вы можете напрямую использовать его функцию echofilter():
echofilter(input, output, delay=0.7, atten=4)
Обратите внимание, что при использованииfrom package import itemв такой форме соответствующий item может быть либо подмодулем (подпакетом) в пакете, либо другими именами, определёнными в пакете, такими как функции, классы или переменные.
Инструкция import сначала рассматривает item как имя, определённое в пакете. Если оно не найдено, она пытается импортировать его как модуль. Если всё ещё не найдено, она вызывает исключение:exc:ImportError.
С другой стороны, если вы используете форму вродеimport item.subitem.subsubitem, то в этом варианте импорта всё, кроме последнего элемента, должно быть пакетом, а последний элемент может быть модулем или пакетом, но не может быть именем класса, функции или переменной.
Импорт * из пакета
Если мы используемfrom sound.effects import *, что произойдёт?
Python обратится к файловой системе, найдёт все подмодули в пакете и импортирует их все один за другим.
Но этот метод работает не очень хорошо на платформе Windows, потому что Windows — регистронезависимая система.
В Windows мы не можем определить, импортируется ли файл с именем ECHO.py как модуль с именем echo, Echo или ECHO.
Чтобы решить эту проблему, нам нужно всего лишь предоставить явный индекс пакета.
Инструкция import следует такому правилу: если файл определения пакета __init__.pyсодержит переменную-список с именем__all__, то при использованииfrom package import *все имена в этом списке импортируются как содержимое пакета.
Как автор пакета, не забудьте убедиться, что после обновления пакета__all__также обновляется.
Следующий пример содержит следующий код в файле sounds/effects/__init__.py:
__all__ = ["echo", "surround", "reverse"]
Это означает, что при использовании from sound.effects import * вы импортируете только эти три подмодуля в пакете.
Если__all__действительно не определён, то использованиеfrom sound.effects import *с этим синтаксисом не импортирует ни один подмодуль из пакета sound.effects. Оно импортирует только пакет sound.effects и всё содержимое, определённое в нём (возможно, выполняя код инициализации, определённый в __init__.py).
Это импортирует все имена, определённые в __init__.py. И это не нарушит никакие явно указанные модули, которые мы импортировали до этого оператора. Взгляните на эту часть кода:
import sound.effects.echo import sound.effects.surround from sound.effects import *
В этом примере перед выполнением from...import модули echo и surround в пакете sound.effects уже были импортированы в текущее пространство имён. (Конечно, если __all__ определён, проблемы нет вообще.)
Обычно мы не рекомендуем использовать*этот метод для импорта модулей, потому что он часто снижает читаемость кода. Однако он действительно может сэкономить много ввода, и некоторые модули предназначены для импорта только определёнными способами.
Помните, что использованиеfrom Package import specific_submoduleэтого метода никогда не бывает ошибочным. Фактически это также рекомендуемый метод. Если только подмодуль, который вы хотите импортировать, не может иметь такое же имя, как подмодуль в другом пакете.
Если пакет является подпакетом в структуре (например, в данном случае для пакета sound), и вы хотите импортировать соседний пакет (пакет на том же уровне), необходимо использовать абсолютный путь для его импорта. Например, если модуль sound.filters.vocoder хочет использовать модуль echo из пакета sound.effects, нужно написать from sound.effects import echo.
from . import echo from .. import formats from ..filters import equalizer
Как неявный, так и явный относительный импорт начинаются с текущего модуля. Имя главного модуля всегда "__main__". Главный модуль приложения Python всегда должен использовать ссылки с абсолютными путями.
Пакеты также предоставляют дополнительный атрибут __path__. Это список каталогов, в каждом из которых есть __init__.py, обслуживающий этот пакет. Его необходимо определить до выполнения других файлов __init__.py. Эту переменную можно изменять, чтобы влиять на модули и подпакеты, содержащиеся в пакете.
Эта возможность используется нечасто; обычно она применяется для расширения модулей в пакете.
Другие расширения