Главная страница
Навигация по странице:

  • 24.1. Способы импортирования

  • 24.5. Организация импортирования

  • СОВЕТ Сгруппированные команды импортирования удобно упорядочить по алфа- виту.СОВЕТ

  • 25.3. Импортирование пакетов

  • Как устроен Python. Как устроен Python. Харрисон. Харрисон Мэтт


    Скачать 5.41 Mb.
    НазваниеХаррисон Мэтт
    АнкорКак устроен Python
    Дата05.02.2022
    Размер5.41 Mb.
    Формат файлаpdf
    Имя файлаКак устроен Python. Харрисон.pdf
    ТипДокументы
    #352210
    страница19 из 21
    1   ...   13   14   15   16   17   18   19   20   21
    232
    Глава 23. Исключения
    23.8. Определение собственных
    исключений
    В модуле exceptions определено много встроенных исключений. Если ваша ошибка хорошо соответствует какому-то существующему исключе- нию, используйте его. Ниже представлена иерархия классов встроенных исключений:
    BaseException
    SystemExit
    KeyboardInterrupt
    GeneratorExit
    Exception
    StopIteration
    ArithmeticError
    FloatingPointError
    OverflowError
    ZeroDivisionError
    AssertionError
    AttributeError
    BufferError
    EnvironmentError
    IOError
    OSError
    EOFError
    ImportError
    LookupError
    IndexError
    KeyError
    MemoryError
    NameError
    UnboundLocalError
    ReferenceError
    RuntimeError
    NotImplementedError
    SyntaxError
    IndentationError
    TabError
    SystemError
    TypeError
    ValueError
    UnicodeError
    UnicodeDecodeError

    23.9. Итоги
    233
    UnicodeEncodeError
    UnicodeTranslateError
    Warning
    DeprecationWarning
    PendingDeprecationWarning
    RuntimeWarning
    SyntaxWarning
    UserWarning
    FutureWarning
    ImportWarning
    UnicodeWarning
    BytesWarning
    Для определения собственных исключений субклассируйте класс
    Exception или один из его субклассов. Дело в том, что все остальные субклассы
    BaseException не обязательно являются «исключениями».
    Например, если вы перехватываете
    KeyboardInterrupt
    , вам не удастся прервать выполнение процесса клавишами
    Ctrl+C
    . Если вы перехватите
    GeneratorExit
    , перестанут работать генераторы.
    Вот как выглядит исключение для определения нехватки информации в программе:
    >>> class DataError(Exception):
    ... def __init__(self, missing):
    ... self.missing = missing
    Использовать нестандартное исключение достаточно просто:
    >>> if 'important_data' not in config:
    ... raise DataError('important_data missing')
    23.9. Итоги
    В этой главе были представлены стратегии обработки исключений.
    В стратегии LBYL перед выполнением операции вы проверяете, что в текущей ситуации не будет выдана ошибка. В стратегии EAFP весь код, который может выдать ошибку, заключается в блок try
    /
    catch
    . В Python предпочтение отдается второму стилю программирования.
    Также были рассмотрены различные механизмы перехвата ошибок, их выдачи и повторной выдачи. В завершение главы было показано, как

    234
    Глава 23. Исключения субклассировать существующие исключения для создания ваших соб- ственных исключений.
    23.10. Упражнения
    1. Напишите программу, выполняющую функции простейшего каль- кулятора. Программа получает два числа, а затем запрашивает опе- ратор. Обеспечьте корректную обработку ввода, который не преоб- разуется в числа. Обработайте ошибки деления на ноль.
    2. Напишите программу, которая вставляет нумерацию перед строка- ми файла. Имя файла передается программе в командной строке.
    Импортируйте модуль sys и прочитайте имя файла из списка sys.
    argv
    . Корректно обработайте возможность передачи несуществую- щего файла.

    24
    Импортирование
    библиотек
    В предыдущих главах были рассмотрены основные конструкции языка
    Python. Эта глава посвящена импортированию кода. Во многих языках существует концепция библиотек, или блоков кода, предназначенных для повторного использования. Python поставляется с большой подборкой библиотек, однако, чтобы извлечь пользу из этих библиотек, вы должны уметь пользоваться ими.
    Чтобы использовать библиотеку, нужно загрузить код из библиотеки в пространство имен вашей программы. Пространство имен содержит функции, классы и переменные, доступные для программы. Если вы хо- тите вычислить синус угла, вам придется определить функцию, которая выполняет эти вычисления, или же загрузить готовую функцию. Встро- енная библиотека math содержит функцию sin для вычисления синуса угла, выраженного в радианах. Библиотека также содержит переменную, определяющую значение «пи»:
    >>> from math import sin, pi
    >>> sin(pi/2)
    1.0
    Приведенный фрагмент загружает модуль math
    . Тем не менее он не поме- щает math в ваше пространство имен. Вместо этого он создает переменную, которая указывает на функцию sin из модуля math
    . Он также создает переменную, указывающую на переменную pi из модуля math
    . Если вы

    236
    Глава 24. Импортирование библиотек проанализируете текущее пространство имен при помощи функции dir
    , вы сможете убедиться в этом:
    >>> 'sin' in dir()
    True
    24.1. Способы импортирования
    В предыдущем примере мы импортировали одну функцию из библио- теки. Также можно загрузить библиотеку в пространство имен и обра- щаться ко всем классам, функциям и переменным. Чтобы импортировать модуль math в пространство имен, введите следующую команду:
    >>> import math
    В этом примере импортируется библиотека math
    . При этом создается новая переменная math
    , указывающая на модуль. Этот модуль содержит разные атрибуты, список которых можно вывести функцией dir
    :
    >>> dir(math)
    ['__doc__', '__file__', '__loader__', '__name__',
    '__package__', '__spec__', 'acos', 'acosh', 'asin',
    'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign',
    'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp',
    'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp',
    'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose',
    'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log',
    'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow',
    'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc']
    Большинство этих атрибутов составляют функции. Если вы хотите вы- звать функцию tan
    , сделать это не удастся, потому что имя tan не входит в ваше пространство имен — только math
    . Однако вы можете провести поиск по переменной math с использованием оператора «точка» (
    ). Этот оператор просматривает атрибуты объекта. Так как в Python нет ничего, кроме объектов, вы можете воспользоваться этим оператором для поиска атрибута tan объекта math
    :
    >>> math.tan(0)
    0.0

    24.1. Способы импортирования
    237
    Импорт библиотек import math tan sin
    Id:1aea math
    Id:1ca8
    __class__:function
    __class__:module
    Id:1ca8
    Код
    Что делает компьютер
    Переменные
    Объекты
    __class__:function
    Рис. 24.1. Импорт модуля. Обратите внимание, что этот код создает новую переменную math, которая указывает на модуль. Модуль имеет различные атрибуты, к которым вы можете получить доступ, использовав период
    Если вы захотите прочитать документацию по функции tan
    , восполь- зуйтесь функцией help
    :
    >>> help(math.tan)
    Справка по встроенной функции tan в модуле math:
    tan(...)
    tan(x)
    Возвращает тангенс x (в радианах).

    238
    Глава 24. Импортирование библиотек
    СОВЕТ
    Когда импортировать функцию с использованием from
    , а когда следует вы- брать команду import
    ? Если вы используете только пару атрибутов из библи- отеки, используйте механизм импортирования в стиле from
    . В конструкции from можно перечислить несколько атрибутов, разделенных запятыми:
    >>> from math import sin, cos, tan
    >>> cos(0)
    1.0
    Но если вам нужно обращаться к большей части библиотеки, будет проще импортировать библиотеку командой import
    . Такое решение также подскажет каждому, кто будет читать ваш код (включая вас), откуда взялась та или иная функция (класс, переменная).
    ПРИМЕЧАНИЕ
    Если вам нужно импортировать несколько атрибутов из библиотеки, команда может занять несколько строк. Если вы попробуете продолжить импортиро- вание функций в следующей строке, произойдет ошибка:
    >>> from math import sin,
    ... cos
    Traceback (most recent call last):
    File "", line 1, in
    SyntaxError: trailing comma not allowed without surrounding parentheses
    Чтобы показать, что команда продолжается в следующей строке, поставьте символ
    \
    :
    >>> from math import sin,\
    ... cos
    Также возможен другой вариант — перечислить импортируемые имена в кру- глых скобках. Открывающая круглая скобка (или квадратная, или фигурная) показывает, что команда продолжается в следующей строке:
    >>> from math import (sin,
    ... cos)
    Последняя форма считается более идиоматичной для Python.

    24.2. Конфликты имен при импортировании
    239
    24.2. Конфликты имен при импортировании
    Если вы работаете над программой, выполняющей тригонометрические операции, у вас уже может быть определена функция с именем sin
    . А если вы также захотите использовать функцию sin из библиотеки math
    ? Одно из возможных решений — импортировать math
    ; тогда запись math.sin будет обозначать библиотечную версию, а sin
    — вашу функцию.
    Python также предоставляет другую возможность. Вы можете переопре- делить импортируемое имя при помощи ключевого слова as
    :
    >>> from math import sin as other_sin
    >>> other_sin(0)
    0.0
    Теперь other_sin представляет собой ссылку на версию sin из math
    , а вы можете продолжать использовать sin без необходимости рефакторинга кода.
    Ключевое слово as также работает с командами import
    . Если у вас имеется переменная (или функция), имя которой конфликтовало с именем из math в вашем пространстве имен, следующий фрагмент демонстрирует одно из возможных решений:
    >>> import math as other_math
    >>> other_math.sin(0)
    0.0
    СОВЕТ
    Ключевое слово as также поможет сделать код более компактным. Если в вашей любимой библиотеке используются слишком длинные имена, вы можете легко сократить их в своем коде. Пользователи библиотеки Numpy
    1
    приняли в качестве стандарта сокращенные имена из двух букв:
    >>> import numpy as np
    Аналогичный стандарт был принят в библиотеке Pandas
    2
    :
    >>> import pandas as pd
    1
    numpy.org
    2
    pandas.pydata.org

    240
    Глава 24. Импортирование библиотек
    24.3. Массовое импортирование
    Python также позволяет загромоздить пространство имен так называе- мым массовым импортированием:
    >>> from math import *
    >>> asin(0)
    0.0
    В этом коде вызывается функция арксинуса, которая не была определена в коде. Та строка, в которой вызывается asin
    , содержит первое упоми- нание asin в коде. Что произошло? Когда вы используете команду math import
    *
    , эта команда приказывает Python загрузить все содержимое библиотеки math
    (определения классов, функции и переменные) в ло- кальное пространство имен. Хотя такая возможность на первый взгляд кажется удобной, на самом деле она довольно опасна.
    Массовое импортирование усложняет отладку, потому что оно не вы- ражает явно, откуда взялся тот или иной код. Еще больше проблем воз- никает с массовым импортированием из нескольких библиотек. Более поздние команды импортирования могут переопределить что-то такое, что было определено в более ранней библиотеке. По этой причине ис- пользовать массовое импортирование не рекомендуется.
    СОВЕТ
    Не используйте массовое импортирование!
    Возможные исключения из этого правила встречаются разве что при само- стоятельном написании кода тестирования или при экспериментах в REPL.
    Авторы библиотек применяют эту конструкцию для импортирования всего содержимого библиотеки, которую они собираются протестировать. Не используйте массовое импортирование только потому, что вы увидели его в чужом коде.
    Вспомните Дзен Python:
    «Явное лучше, чем неявное».

    24.5. Организация импортирования
    241
    24.4. Вложенные библиотеки
    У некоторых пакетов Python есть вложенное пространство имен. Напри- мер, библиотека XML, входящая в поставку Python, включает поддержку minidom и etree
    . Обе библиотеки размещаются внутри родительского пакета xml
    :
    >>> from xml.dom.minidom import \
    ... parseString
    >>> dom = parseString(
    ... '')
    >>> from xml.etree.ElementTree import \
    ... XML
    >>> elem = XML('')
    Конструкция from позволяет импортировать только нужные функции и классы. Конструкция import
    (без from
    ) увеличивает объем кода (но также открывает доступ ко всему содержимому пакета):
    >>> import xml.dom.minidom
    >>> dom = xml.dom.minidom.parseString(
    ... '')
    >>> import xml.etree.ElementTree
    >>> elem = xml.etree.ElementTree.XML(
    ... '')
    24.5. Организация импортирования
    Согласно PEP 8, команды импортирования должны располагаться в на- чале файла за строкой документации модуля. В каждой строке должна находиться одна команда import
    , причем команды import должны быть объединены в группы:
    
    Импортирование из стандартной библиотеки.
    
    Импортирование из стороннего кода.
    
    Импортирование из локальных пакетов.

    242
    Глава 24. Импортирование библиотек
    Например, начало модуля может выглядеть так:
    #!/usr/bin/env python3
    """
    Модуль преобразует записи в JSON
    и сохраняет их в базе данных """
    import json # Стандартные библиотеки import sys import psycopg2 # Сторонние библиотеки import recordconverter # Локальные библиотеки
    СОВЕТ
    Сгруппированные команды импортирования удобно упорядочить по алфа- виту.
    СОВЕТ
    Иногда команды импортирования бывает полезно отложить по следующим причинам:
    • Для предотвращения циклического импортирования (ситуации, при кото- рой модули импортируют друг друга). Если вы не можете (или не хотите) провести рефакторинг для предотвращения циклического импортирова- ния, команду import можно разместить в функции или методе с тем кодом, из которого вызываются импортируемые элементы.
    • Для предотвращения импортирования модулей, недоступных в некоторых системах.
    • Для предотвращения импортирования больших модулей, не используе- мых в программе.

    24.7. Упражнения
    243
    24.6. Итоги
    В этой главе рассматривалось импортирование библиотек в Python.
    У Python имеется большая стандартная библиотека
    1
    , и вам нужно будет импортировать эти библиотеки для использования в коде. В книге не- однократно подчеркивалось, что в Python нет ничего, кроме объектов, и вы часто создаете переменные, указывающие на эти объекты. При импортировании модуля создается переменная, указывающая на объект модуля. После этого вы можете обратиться к любым элементам про- странства имен модуля при помощи операции поиска (
    ).
    Также можно избирательно импортировать части пространства имен модуля командой from
    . Если вы хотите переименовать импортируемый элемент, воспользуйтесь конструкцией as
    24.7. Упражнения
    1. Найдите в стандартной библиотеке Python пакет для работы с JSON.
    Импортируйте библиотечный модуль и просмотрите атрибуты.
    Используйте функцию help для получения более подробной инфор- мации об использовании модуля. Сериализуйте словарь, связываю- щий ключ 'name'
    с вашим именем и ключ 'age'
    с вашим возрастом, в строку JSON. Проведите десериализацию JSON в Python.
    2. Найдите в стандартной библиотеке Python пакет для вывода со- держимого каталогов. Используйте этот пакет и напишите функ- цию, которая получает имя каталога, получает список всех файлов в этом каталоге и выводит отчет с количеством файлов для каждо- го расширения.
    1
    https://docs.python.org/3/library/index.html

    25
    Библиотеки:
    пакеты и модули
    В главе 24 вы научились импортировать библиотеки. В этой главе мы разберемся в том, что же представляет собой библиотека. При импорти- ровании библиотеки действуют два требования:
    1. Библиотека должна представлять собой модуль или пакет.
    2. Библиотека должна находиться в месте, определяемом переменной среды
    PYTHONPATH
    или переменной Python sys.path
    25.1. Модули
    Модули представляют собой файлы Python с расширением
    .py и именем, пригодным для импортирования. Согласно PEP 8, имена файлов модулей должны быть короткими и записываться в нижнем регистре. Символы подчеркивания могут использоваться для удобства чтения.
    25.2. Пакеты
    Пакет в Python представляет собой каталог, содержащий файл с именем
    __init__.py
    . Файл
    __init__.py может содержать любую реализацию (или во- обще быть пустым). Кроме того, каталог может содержать произвольное количество модулей и субпакетов.

    25.3. Импортирование пакетов
    245
    Что лучше использовать при написании кода — модуль или пакет?
    Я обычно начинаю с более простого варианта и использую модуль. А если мне нужно выделять отдельные части в собственные модули, я преоб- разую модули в пакет.
    Пример структуры каталога из популярного проекта SQLAlchemy
    1
    (сред- ство объектно-реляционного отображения для баз данных):
    sqlalchemy/
    __init__.py engine/
    __init__.py base.py schema.py
    Согласно PEP 8, имена каталогов пакетов должны быть короткими и записываться в нижнем регистре. Символы подчеркивания в них не- допустимы.
    25.3. Импортирование пакетов
    Чтобы импортировать пакет, используйте команду import с именем пакета
    (именем каталога):
    >>> import sqlalchemy
    Эта команда импортирует файл sqlalchemy/__init__.py в текущее простран- ство имен, если пакет будет найден в
    PYTHONPATH
    или sys.path
    Если вы захотите использовать классы
    Column и
    ForeignKey из модуля schema.py
    , подойдет любой из следующих фрагментов. Первый включает sqlalchemy.schema в ваше пространство имен, а второй помещает в про- странство имен только schema
    :
    >>> import sqlalchemy.schema
    >>> col = sqlalchemy.schema.Column()
    >>> fk = sqlalchemy.schema.ForeignKey()
    1
    https://www.sqlalchemy.org/

    246
    Глава 25. Библиотеки: пакеты и модули или
    >>> from sqlalchemy import schema
    >>> col = schema.Column()
    >>> fk = schema.ForeignKey()
    А если вам нужен только класс
    Column
    , импортируйте этот класс одним из двух способов:
    >>> import sqlalchemy.schema.Column
    >>> col = sqlalchemy.schema.Column()
    или
    >>> from sqlalchemy.schema import Column
    >>> col = Column()
    25.4. PYTHONPATH
    Переменная среды
    PYTHONPATH
    содержит список нестандартных катало- гов, в которых Python ищет модули или пакеты. Обычно эта перемен- ная пуста. Изменять
    PYTHONPATH
    обычно не обязательно, если только вы в процессе разработки не хотите использовать библиотеки, которые еще не были установлены.
    1   ...   13   14   15   16   17   18   19   20   21


    написать администратору сайта