Кеннет Рейтц – Автостопом по Python (страница 39)
Одновременно с отладкой мы можем открыть файл исходного кода и следовать по нему. Если мы продолжим подниматься по стеку, то увидим, где вызвано приложение WSGI:
(Pdb) u
> /[… truncated path…]/flask/flask/app.py(1624)full_dispatch_request()
-> rv = self.dispatch_request()
(Pdb) u
> /[… truncated path…]/flask/flask/app.py(1973)wsgi_app()
-> response = self.full_dispatch_request()
(Pdb) u
> /[… truncated path…]/flask/flask/app.py(1985)__call__()
-> return self.wsgi_app(environ, start_response)
Если мы продолжим вводить u, то окажемся в модуле тестирования, который был использован для создания фальшивого клиента без запуска сервера, — мы достигли конца стека. Мы узнали, что приложение flaskr отправляется изнутри объекта класса flask.app.Flask, строка 1985 файла Flask/Flask/app.py. Перед вами эта функция:
Мы используем отладчик точно так же, как граф вызовов для HowDoI: следуем вызовам функций (это в принципе не отличается от чтения самого кода). Ценность отладчика заключается в том, что мы не видим лишнего кода, который может отвлечь нас или запутать. Используйте тот подход, который наиболее эффективен для вас.
После того как мы поднялись по стеку с помощью команды u, можем вернуться вниз с помощью команды d — и снова окажемся у точки останова, помеченной *** Newest frame:
> /[… truncated path…]/flask/examples/flaskr/flaskr.py(74)show_entries()
-> db = get_db()
(Pdb) d *** Newest frame
Далее можем перейти через вызов функции с помощью команды n (next — «далее») или же сделать минимально возможный шаг с помощью команды s (step — «шаг»):
Тема на этом не заканчивается, но демонстрировать весь материал довольно утомительно. Вот что мы узнали.
Отладчик полезно использовать локально в том месте, которое вы проверяете, чтобы точно понять, что происходит в коде до и после выбранной пользователем точки. Одной из основных функций является возможность изменять переменные на ходу (любой код Python работает в отладчике), после чего вы можете продолжить выполнение кода.
Diamond содержит пример журналирования в приложении, а Flask предоставляет такой пример в библиотеке. Если вы хотите лишь избежать предупреждений «обработчик не обнаружен», выполните поиск строки logging в библиотеке Requests (requests/requests/__init__.py). Но если вам необходимо предоставить поддержку журналирования в вашей библиотеке или фреймворке, следует воспользоваться примером, предоставляемым Flask.
Журналирование во Flask реализовано в файле Flask/Flask/logging.py. В нем определяется формат строк журнала для производства (уровень журналирования ERROR) и отладки (уровень журналирования DEBUG), также автор кода следует советам из Twelve-Factor App (http://12factor.net/) по записи журналов в потоки (которые направляются в потоки wsgi.errors или sys.stderr в зависимости от контекста).
Средство журналирования добавляется в основное приложение Flask в Flask/Flask/app.py (в следующем фрагменте кода опущена вся нерелевантная информация).
Примеры стиля из Flask
Большая часть примеров стиля из главы 4 уже была рассмотрена, поэтому для Flask мы продемонстрируем всего один — реализацию элегантных и простых декораторов маршрутизации.
Декораторы для маршрутизации во Flask (красивое лучше, чем уродливое). Декораторы для маршрутизации во Flask добавляют маршрутизацию URL к целевым функциям, например так:
@app.route('/')
def index():
····pass
При отправке запроса приложение Flask будет использовать маршрутизацию URL для определения корректной функции, которая нужна для генерации ответа. Синтаксис декоратора позволяет хранить логику маршрутизации за пределами целевой функции, поддерживает функции flat, а его использование интуитивно.
Делать это вовсе необязательно — он существует только для того, чтобы предоставить пользователю данную функциональность API. Рассмотрим исходный код метода основного класса Flask, определенного в файле Flask/Flask/app.py.
Примеры структуры из Flask
Основной посыл для обоих примеров структуры для Flask — модульность. Flask целенаправленно структурирован так, чтобы вы могли расширять и модифицировать практически все что угодно — от способа кодирования/декодирования строк JSON (Flask дополняет функциональность стандартной библиотеки для работы с JSON возможностью задавать кодировки для объектов datetime и UUID) до классов, использованных для маршрутизации URL.
Стандарты, характерные для приложения (простое лучше, чем сложное)
Flask и Werkzeug имеют модуль wrappers.py. Он нужен, чтобы добавить соответствующие значения по умолчанию во Flask, фреймворк для веб-приложений, которые будут дополнять общую библиотеку вспомогательных программ для приложений WSGI от Werkzeug. Во Flask создаются подклассы для Request и Response Werkzeug для того, чтобы добавлять функциональность, характерную для веб-приложений. Например, объект Response из файла Flask/Flask/wrappers.py выглядит так:
В этой небольшой интерактивной сессии показывается, что изменилось в классе Response:
>>> import werkzeug
>>> import flask
>>>
>>> werkzeug.wrappers.Response.default_mimetype
'text/plain'
>>> flask.wrappers.Response.default_mimetype
'text/html'
>>> r1 = werkzeug.wrappers.Response('hello', mimetype='text/html')
>>> r1.mimetype
u'text/html'
>>> r1.default_mimetype
'text/plain'
>>> r1 = werkzeug.wrappers.Response('hello')