Inspect python: inspect — Inspect live objects — Python 3.9.0 documentation
module | __doc__ | строка документации | |
__file__ | имя файла (отсутствует
для встроенных модулей) | ||
class | __doc__ | строка документации | |
__module__ | имя модуля в котором
определён этот класс | ||
method | __doc__ | строка документации | |
__name__ | имя, с которым был
определён этот метод | ||
im_class | объект класса, у которого
запрашивается этот метод | (1) | |
im_func или
__func__ | объект функции,
содержащий реализацию метода | ||
im_self or
__self__ | экземлпяр, к которому
привязан метод, или None | ||
function | __doc__ | строка документации | |
__name__ | имя, с которым эта функция
была определена | ||
func_code | объект кода, содержащий
скомпилированный bytecode функции | ||
func_defaults | кортеж значений по
умолчанию для аргументов | ||
func_doc | (то же, что и __doc__) | ||
func_globals | глобальное пространство
имён, в котором была определена функция | ||
func_name | (то же, что и __name__) | ||
generator | __iter__ | определена для поддержки
итерации через контейнер | |
close | вызывает исключение
GeneratorExit внутри генератора, чтобы прекратить итерацию | ||
gi_code | объект кода | ||
gi_frame | объект фрейма или,
возможно, None, если генератор был исчерпан | ||
gi_running | равен 1, если генератор
исчерпан, иначе 0 | ||
next | возвращает следующий
элемент из контейнера | ||
send | возобновляет генератор и
“посылает” значение, которое становится результатом текущего выражения yield | ||
throw | используется для
возбуждения исключения внутри генератора | ||
traceback | tb_frame | объект фрейма на этом
уровне | |
tb_lasti | индекс последней
применённой инструкции в байткоде | ||
tb_lineno | номер текущей строки в
исходном коде Python | ||
tb_next | следующий внутренний
объект трассировки (вызываемый на этом уровне) | ||
frame | f_back | следующий внешний объект
фрейма (вызывающий этот фрейм) | |
f_builtins | встроенное пространство
имён, видимое этим фреймом. | ||
f_code | объект кода, выполняемый
в этом фрейме | ||
f_exc_traceback | трассировка, если есть в
этом фрейме, иначе None | ||
f_exc_type
f_exc_type | тип исключения, если
возникает в этом фрейме, иначе None | ||
f_exc_value | значение исключения, если
возникает в этом фрейме, иначе None | ||
f_globals
f_globals | глобальное пространство
имён, видимое этим фреймом | ||
f_lasti
f_lasti | индекс последней
выполненной инструкции в байткоде | ||
f_lineno | номер текущей строки в
исходном коде Python | ||
f_locals
f_locals | локальное пространство
имён, видимое в этом фрейме | ||
f_restricted | 0 или 1, если фрейм
находится в ограниченном режиме выполнения | ||
f_trace | трассировочная функци
для этого фрейма, или None | ||
code | co_argcount | число аргументов (не
включая аргументы * или **) | |
co_code | строка, или сырой
скомпилированный байт-код | ||
co_consts
co_consts | кортеж констант,
используемых в байт-коде | ||
co_filename | имя файла, в котором этот
объект кода был создан | ||
co_firstlineno | номер первой строки в
исходном коде Python | ||
co_flags | bitmap: 1=optimized |
2=newlocals | 4=*arg
| 8=**arg | ||
co_lnotab | кодированое отображение
номер стр+оки на индекс байт-кода | ||
co_name | имя, с которым этот
объект кода был определён | ||
co_names | кортеж имён локальных
переменных | ||
co_nlocals
co_nlocals | количество локальных
переменных | ||
co_stacksize | требуемый стек для
виртуальной машины | ||
co_varnames | кортеж имён аргументов
и локальных переменных | ||
builtin | __doc__ | строка документации | |
__name__ | оригинальне имя этой
функции или метода | ||
__self__ | экземпляр, к которому
привязан этот метод, или None |
PEP 257 на русском. (Соглашение о Docstrings) / Хабр
Привет, Хабр. Бывают моменты, когда тебе хочется максимально погрузиться в язык и понять все его тонкости. В случае Python один из лучших способов это сделать — читать на официальном сайте документацию и PEP-ы. В своё время я этого не делал, поскольку не мог понять многих «технических» моментов, а вариантов русского перевода не было. Сейчас же я решил сам перевести PEP-257, где рассказывается о правильном документировании кода, ведь наверняка это поможет новичкам лучше понять истинный «пайтоновский» подход к написанию кода. Я переводил примеры кода на русский язык, но только для того, чтобы лучше донести смысл. В реальном программировании старайтесь писать документационные строки на английском. Также говорю сразу, что как синоним термина «docstring» я использовал слова: «документация» и «документационные строки». Что же, перейдём к самому переводу.
Аннотация
Данный PEP документирует семантику и соглашения, связанные с использованием Python docstrings.
Обоснование
Целью данного PEP является стандартизация высокоуровневой структуры документационных строк: описать, что именно они должны содержать и объяснять (При этом мы не будем обговаривать фактический синтаксис разметки). PEP содержит не жесткие предписания, а рекомендации:
«Общепринятые соглашения обеспечивают ясность, логичность, удобство сопровождения и воспитывают хорошие программистские привычки. Но они не заставляет вас действовать против своей воли. Это Python!»
Тим Питерс на comp.lang.python, 2001-06-16
Если вы избегаете общепринятых соглашений, в худшем случае на вас посмотрят искоса. Но существуют некоторые приложения (Например, системы документирования, подобные Docutils), которые позволят вам добиться более качественного результата, если вы знаете о договорённостях и будете им следовать.
Спецификация
Что такое Docstring?
Документационная строка — это строковый литерал, являющийся первой инструкцией в определении модуля, функции, класса или метода. Такая строка становится доступна при обращении с специальному атрибуту __doc__ этого объекта.
Все библиотеки, а также функции и классы, экспортируемые ими, должны иметь docstring. Публичные методы (включая конструктор __ init__) также должны иметь документацию. Сам же пакет может быть задокументирован внутри файла __init__.py, находящегося в соответствующей ему директории.
Строковые литералы, встречающиеся в других местах кода, также могут играть роль документации. Они не распознаются Python компилятором байт-кода и недоступны в качестве атрибутов объекта во время выполнения программы (т. е. у них отсутствует информация в __ doc__ ). Но существуют два дополнительных типа документационных строк, которые извлекаются с помощью других программных средств:
- Строковые литералы, встречающиеся сразу после простого присваивания на уровне модуля, класса или метода __init__, называются «строки документации атрибута». (attribute docstrings)
- Строковые литералы, встречающиеся сразу после другой строки документации, называются «дополнительными строками документации». (additional docstrings)
Пожалуйста, смотрите PEP 258, «Спецификация проекта Docutils», где более подробно описываются attribute и additional docstrings.
[прим. ред. Пояснение из PEP 258]
def f(x):
"""Это docstring расположенный в __doc__ функции."""
"""
Это "additional docstrings", он проигнорируется компилятором,
но будет распознан средствами Docutils.
"""
return x**2
f.a = 1
"""Это "attribute docstrings" для атрибута функции: f.a"""
Для согласованности всегда используйте «»»тройные двойные кавычки»»» вокруг документационной строки. Если вы используете символы обратной косой черты («\»), то воспользуйтесь r»»»сырая строка с двойными кавычками»»» в ваших документациях. Для docstring, содержащих Unicode символы, используйте u»»»Юникод строка в тройных двойных кавычках»»». [прим. unicode строки потеряли смысл в python 3.x]
Существует две формы docstring: однострочные и многострочный.
Однострочные документационные строки
Однострочные строки используются для очевидных случаев и они должны действительно находится на одной строке. Например:
def kos_root():
"""Вернёт путь к папке root KOS"""
global _kos_root
if _kos_root: return _kos_root
...
Замечания:
- Тройные кавычки используются даже если строка помещается на одной линии. Это облегчает последующее расширение документации.
- Закрывающие кавычки находятся на той же строке, что и открывающие. Для однострочных docstring это выглядит лучше.
- Ни до, ни после документации не пропускаются строки. Код пишется сразу же на следующей линии
- Документационная строка — это «фраза», заканчивающаяся точкой. Она описывает эффект функции или метода в командном тоне («Сделай это», «Верни это»), не являясь простым описанием. Например, не пишите подобные документации: «Возвращает путь …».
Примечание переводчикаЗначение фразы «командный тон» в английском языке можно пояснить на примере словосочетаний «Return pathname» и «Returns pathname». PEP-257 просит придерживаться первого стиля, потому что он более строгий.
- Однострочная документация НЕ должна быть простой «подписью», повторяющей параметры функции/метода (которые могут быть получены путем инспектирования). Не делайте так:
def function(a, b): """function(a, b) -> list"""
Этот вид документаций подходит только для функций, написанных на языке C (таких как встроенные), где самоанализ невозможен. Также стоит упомянуть о природе возвращаемого значения. Предпочтительной формой для такой документационной строки будет что-то вроде:def function(a, b): def function(a, b): """Сделай X и верни список."""
(И конечно-же, «Сделай X» дожно быть заменено полезным описанием!)
Примечание переводчикаДа, я только что писал выше: «Документация не является простым описанием», но в оригинале Гвидо и Дэвид действительно используют одинаковое слово «description» в этих двух местах. Думаю, что не стоит слишком придираться к этому, ведь посыл и так ясен.
Многострочные документационные строки
Многострочные документации состоят из сводной строки (summary line) имеющей такую же структуру, как и однострочный docstring, после которой следует пустая линия, а затем более сложное описание. «Summary line» может быть использована средствами автоматического документирования; поэтому так важно располагать её на одной строке и после делать пропуск в одну линию. Сводная строка пишется сразу после открывающихся кавычек, но допускается сделать перенос и начать со следующей строки. [прим. после этого предложения я был счастлив, ведь находились люди, которые упорно пытались мне доказать, что делать перенос ни в коем случае нельзя 🙂 ] При этом, весь docstring должен иметь такой же отступ, как и открывающие кавычки первой строки (см. пример ниже).
Оставляйте пустую строку после всех документаций (однострочных или многострочных), которые используются в классе; вообще говоря, методы класса должны быть отделены друг от друга одной пустой линией, поэтому документационная строка класса также должна быть отделена этим способом от первого метода.
Документация скрипта (автономной программы) представляет из себя сообщение «о правильном использовании» и возможно будет напечатано, когда скрипт вызовется с неверными или отсутствующими аргументами (или же с опцией «-h», для получения «help»). Такая документационная строка должна описывать функционал и синтаксис параметров скрипта, а также переменные среды и используемые файлы. Данное сообщение может оказаться довольно сложным (мануал длиной в несколько полных экранов), но при этом оно должно быть удобным для новых пользователей, чтобы они смогли использовать команду правильно. Также мануал должен давать чёткое описание всех параметров и аргументов для более опытных пользователей.
Документация модуля должна обычно содержать список классов, исключений и функций (и любых других важных объектов), которые экспортируются при помощи библиотеки, а также однострочное пояснение для каждого из них. (Это резюме, как правило, даёт меньше деталей, чем summary line в docstring самого объекта). В документации пакета (т. е. docstring модуля в __init__.py ) следует также описать и перечислить модули и подпакеты, экспортируемые главным.
Документация функции или метода должна описывать их поведение, аргументы, возвращаемые значения, побочные эффекты, возникающие исключения и ограничения на то, когда они могут быть вызваны (если это вообще предусмотрено). Также необходимо указать необязательные аргументы. Должно быть уточнено, являются ли ключевые аргументы частью интерфейса.
Документация класса должна обобщать его поведение и перечислять открытые методы, а также переменные экземпляра. Если класс будет иметь подклассы с дополнительный интерфейсом, то этот интерфейс должен быть указан отдельно (но всё также в этой документации). Конструктор класса должен иметь свою отдельную документационную строку для метода __init__. Независимые (индивидуальные) методы должны иметь собственную документацию.
Если класс является потомком и его поведение в основном наследуется от основного класса, в его документации необходимо упомянуть об этом и описать возможные различия. Используйте глагол «override» («переопределить»), чтобы указать факт подмены метода и что вследствие этого метод суперкласса вызываться не будет. Используйте глагол «extends» («расширяет»), если метод подкласса вызывает метод суперкласса (в дополнение к его собственному поведению).
Не используйте соглашение Emacs об упоминании аргументов функций или методов в верхнем регистре. Python чувствителен к регистру, а имена аргументов могут порой использоваться при их передаче по ключам, поэтому документация должна содержать реальные имена переменных. Лучше всего перечислять каждый аргумент в отдельной строке. Например:
def complex(real=0.0, imag=0.0):
"""Сформировать комплексное число.
Ключевые аргументы:
real -- действительная часть (по умолчанию 0.0)
imag -- мнимая часть (по умолчанию 0.0)
"""
if imag == 0.0 and real == 0.0:
return complex_zero
...
Если весь docstring не помещается в строку, вы можете вынести закрывающие кавычки на отдельную линию. Таким образом, можно будет использовать Emacs команду: fill-paragraph
Обработка Docstring
Инструменты обработки документационных строк должны удалять одинаковое количество отступов, равное минимальному отступу всех не пустых строк, начиная со второй. Любые отступы в первой строке документации несущественны и будут удалены. Относительный отступ более поздних строк в строке документа сохраняется. Пустые строки должны быть удалены из начала и конца строки документа.
Поскольку код гораздо точнее слов, здесь приведена реализация алгоритма:
def trim(docstring):
if not docstring:
return ''
# Конвертирует табы в пробелы (согласно нормам Python)
# и разбивает в список из строк:
lines = docstring.expandtabs().splitlines()
# Высчитывает наименьший отступ (первая линия не считается):
indent = sys.maxsize
for line in lines[1:]:
stripped = line.lstrip()
if stripped:
indent = min(indent, len(line) - len(stripped))
# Убираем отступ (особенность первой линии документации):
trimmed = [lines[0].strip()]
if indent < sys.maxsize:
for line in lines[1:]:
trimmed.append(line[indent:].rstrip())
# Убираем пустые строки из начала и конца:
while trimmed and not trimmed[-1]:
trimmed.pop()
while trimmed and not trimmed[0]:
trimmed.pop(0)
# Возвращаем итоговую строку документации:
return '\n'.join(trimmed)
Примечание переводчика
По сравнению с оригинальным кодом, в python3 атрибут sys.maxint был переименован в sys.maxsize, поэтому в коде это сразу исправлено.
Документация в следующем примере содержит два символа новой строки и поэтому имеет длину равную трём. Первая и последняя строки пусты:
def foo ():
"""
Это вторая строка документации.
"""
Проиллюстрируем:
>>> print repr(foo.__doc__)
'\n Это вторая строка документации.\n '
>>> foo.__doc__.splitlines()
['', ' Это вторая строка документации.', ' ']
>>> trim(foo.__doc__)
' Это вторая строка документации.'
Таким образом, после обработки следующие документационные строки будут эквивалентны:
def foo():
"""Документация на
несколько линий.
"""
def bar():
"""
Документация на
несколько линий.
"""
Примечание переводчика
Также не стоит забывать и про модуль inspect, где лежит уже готовая реализация функции форматирования документаций, поэтому с таким же успехом можно было написать: inspect.cleandoc(function.__doc__)
Изучаем трассировку из Python на примерах решения проблем в коде
Python выводит трассировку (далее traceback), когда в вашем коде появляется ошибка. Вывод traceback может быть немного пугающим, если вы видите его впервые, или не понимаете, чего от вас хотят. Однако traceback Python содержит много информации, которая может помочь вам определить и исправить причину, из-за которой в вашем коде возникла ошибка.
Содержание статьи
Понимание того, какую информацию предоставляет traceback Python является основополагающим критерием того, как стать лучшим Python программистом.
К концу данной статьи вы сможете:
- Понимать, что несет за собой traceback
- Различать основные виды traceback
- Успешно вести журнал traceback, при этом исправить ошибку
Python Traceback — Как правильно читать трассировку?
Traceback (трассировка) — это отчет, который содержит вызовы выполненных функций в вашем коде в определенный момент.
Есть вопросы по Python?
На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!
Telegram Чат & Канал
Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!
Паблик VK
Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!
Traceback называют по разному, иногда они упоминаются как трассировка стэка, обратная трассировка, и так далее. В Python используется определение “трассировка”.
Когда ваша программа выдает ошибку, Python выводит текущую трассировку, чтобы подсказать вам, что именно пошло не так. Ниже вы увидите пример, демонстрирующий данную ситуацию:
def say_hello(man):
print(‘Привет, ‘ + wrong_variable)
say_hello(‘Иван’)
| def say_hello(man): print(‘Привет, ‘ + wrong_variable)
say_hello(‘Иван’) |
Здесь say_hello()
вызывается с параметром man
. Однако, в say_hello()
это имя переменной не используется. Это связано с тем, что оно написано по другому: wrong_variable
в вызове print()
.
Обратите внимание: в данной статье подразумевается, что вы уже имеете представление об ошибках Python. Если это вам не знакомо, или вы хотите освежить память, можете ознакомиться с нашей статьей: Обработка ошибок в Python
Когда вы запускаете эту программу, вы получите следующую трассировку:
Traceback (most recent call last):
File «/home/test.py», line 4, in <module>
say_hello(‘Иван’)
File «/home/test.py», line 2, in say_hello
print(‘Привет, ‘ + wrong_variable)
NameError: name ‘wrong_variable’ is not defined
Process finished with exit code 1
| Traceback (most recent call last): File «/home/test.py», line 4, in <module> say_hello(‘Иван’) File «/home/test.py», line 2, in say_hello print(‘Привет, ‘ + wrong_variable) NameError: name ‘wrong_variable’ is not defined
Process finished with exit code 1 |
Эта выдача из traceback содержит массу информации, которая вам понадобится для определения проблемы. Последняя строка трассировки говорит нам, какой тип ошибки возник, а также дополнительная релевантная информация об ошибке. Предыдущие строки из traceback указывают на код, из-за которого возникла ошибка.
В traceback выше, ошибкой является NameError, она означает, что есть отсылка к какому-то имени (переменной, функции, класса), которое не было определено. В данном случае, ссылаются на имя wrong_variable
.
Последняя строка содержит достаточно информации для того, чтобы вы могли решить эту проблему. Поиск переменной wrong_variable
, и заменит её атрибутом из функции на man
. Однако, скорее всего в реальном случае вы будете иметь дело с более сложным кодом.
Python Traceback — Как правильно понять в чем ошибка?
Трассировка Python содержит массу полезной информации, когда вам нужно определить причину ошибки, возникшей в вашем коде. В данном разделе, мы рассмотрим различные виды traceback, чтобы понять ключевые отличия информации, содержащейся в traceback.
Подробный обзор структуры трассировки в Python 3
Существует несколько секций для каждой трассировки Python, которые являются крайне важными. Диаграмма ниже описывает несколько частей:
В Python лучше всего читать трассировку снизу вверх.
- Синее поле: последняя строка из traceback — это строка уведомления об ошибке. Синий фрагмент содержит название возникшей ошибки.
- Зеленое поле: после названия ошибки идет описание ошибки. Это описание обычно содержит полезную информацию для понимания причины возникновения ошибки.
- Желтое поле: чуть выше в трассировке содержатся различные вызовы функций. Снизу вверх — от самых последних, до самых первых. Эти вызовы представлены двухстрочными вводами для каждого вызова. Первая строка каждого вызова содержит такую информацию, как название файла, номер строки и название модуля. Все они указывают на то, где может быть найден код.
- Красное подчеркивание: вторая строка этих вызовов содержит непосредственный код, который был выполнен с ошибкой.
Есть ряд отличий между выдачей трассировок, когда вы запускает код в командной строке, и между запуском кода в REPL. Ниже вы можете видеть тот же код из предыдущего раздела, запущенного в REPL и итоговой выдачей трассировки:
Python 3.7.4 (default, Jul 16 2019, 07:12:58)
[GCC 9.1.0] on linux
Type «help», «copyright», «credits» or «license» for more information.
>>>
>>>
>>> def say_hello(man):
… print(‘Привет, ‘ + wrong_variable)
…
>>> say_hello(‘Иван’)
Traceback (most recent call last):
File «<stdin>», line 1, in <module>
File «<stdin>», line 2, in say_hello
NameError: name ‘wrong_variable’ is not defined
| Python 3.7.4 (default, Jul 16 2019, 07:12:58) [GCC 9.1.0] on linux Type «help», «copyright», «credits» or «license» for more information. >>> >>> >>> def say_hello(man): … print(‘Привет, ‘ + wrong_variable) … >>> say_hello(‘Иван’)
Traceback (most recent call last): File «<stdin>», line 1, in <module> |
Библиотека запросов в Python (Руководство)
Подписывайся на наш канал в Telegram, чтобы ежедневно совершенствоваться в Python. Там выходят задачи, полезные советы и сливы платных курсов — перейти
Оглавление
- Начало работы с запросами
- Запрос GET
- Ответ
- Коды состояния
- Содержание
- Заголовки
- Параметры строки запроса
- Заголовки запроса
- Другие методы HTTP
- Тело сообщения
- Проверка вашего запроса
- Аутентификация
- Проверка SSL сертификата
- Представление
- Таймауты
- Объект сеанса
- Макс повторов
- Вывод
Библиотека requests
фактически является стандартом для создания HTTP – запросов в Python. Он абстрагирует сложности выполнения запросов от красивого и простого API, так что вы можете сосредоточиться на взаимодействии со службами и использовании данных в вашем приложении.
В этой статье вы увидите некоторые из наиболее полезных функций, которые requests
может предложить, а также как настроить и оптимизировать эти функции для различных ситуаций, с которыми вы можете столкнуться. Вы также узнаете, как эффективно использовать requests
, а также как предотвратить замедление запросов к внешним службам.
В этом уроке вы узнаете, как:
- Делать запросы, используя самые распространенные методы HTTP
- Настроить заголовки и данные ваших запросов, используя строку запроса и текст сообщения
- Проверить данные из ваших запросов и ответов
- Делать аутентифицированные запросы
- Настроить свои запросы, чтобы предотвратить резервное копирование или замедление работы приложения.
Хотя я пытался включить столько информации , сколько вам нужно , чтобы понять особенности и примеры , включенные в этой статье, я взял на себя очень базовые общие знания HTTP . Тем не менее, вы все равно можете продолжать не беспокоясь в любом случае.
Теперь, давайте углубимся и посмотрим, как вы можете использовать requests
в своем приложении!
Начало работы с requests
Начнем с установки requests
библиотеки. Для этого выполните следующую команду:
$ pip install requests
Если вы предпочитаете использовать Pipenv для управления пакетами Python, вы можете запустить следующее:
$ pipenv install requests
После установки requests
вы можете использовать его в своем приложении. Импорт requests
выглядит так:
import requests
Теперь, когда вы все настроили, пришло время начать ваше путешествие в requests
. Ваша первая цель будет научиться делать GET
запрос.
Запрос GET
Методы HTTP, такие как GET
и POST
, определяют, какое действие вы пытаетесь выполнить при выполнении запроса HTTP. Кроме того , GET
и POST
есть несколько других распространенных методов , которые вы будете использовать позже в этом руководстве.
Одним из наиболее распространенных методов HTTP является GET
. GET
метод указывает на то, что вы пытаетесь получить, или получить данные из указанного ресурса. Чтобы сделать GET
запрос, вызовите requests.get()
.
Чтобы проверить, вы можете сделать GET
запрос в GitHub Root REST API , вызвав get()
по следующему URL:
>>> requests.get('https://api.github.com')
<Response [200]>
Поздравляем! Вы сделали свой первый запрос. Давайте углубимся в ответ на этот запрос.
Ответ
Response
является мощным объектом для проверки результатов запроса. Давайте сделаем тот же запрос еще раз, но на этот раз сохраняем возвращаемое значение в переменной, чтобы вы могли ближе познакомиться с его атрибутами и поведением:
>>> response = requests.get('https://api.github.com')
В этом примере вы захватили возвращаемое значение get()
, которое является экземпляром Response
, и сохранили его в переменной с именем response
. Теперь вы можете использовать response
, чтобы увидеть много информации о результатах вашего GET
запроса.
Коды состояния
Первым битом информации, которую вы можете получить Response
, является код состояния. Код состояния информирует вас о статусе запроса.
Например, 200 OK
статус означает, что ваш запрос был успешным, тогда как 404 NOT FOUND
статус означает, что ресурс не найден. Есть много других возможных кодов состояния, чтобы дать вам конкретное представление о том, что произошло с вашим запросом.
Получив доступ .status_code
, вы можете увидеть код состояния, который вернул сервер:
>>> response.status_code
200
.status_code
вернул 200
, что означает, что ваш запрос был успешным, и сервер ответил данными, которые вы запрашивали.
Иногда вы можете использовать эту информацию для принятия решений в своем коде:
if response.status_code == 200:
print('Success!')
elif response.status_code == 404:
print('Not Found.')
С этой логикой, если сервер возвращает код состояния 200
, ваша программа напечатает Success!
. Если результат будет 404
, ваша программа напечатает Not Found
.
requests
делает еще один шаг вперед в упрощении этого процесса для вас. Если вы используете Response
экземпляр в условном выражении, он оценит, был ли код состояния True
между 200
, 400
и False
иначе.
Поэтому вы можете упростить последний пример, переписав if
оператор:
if response:
print('Success!')
else:
print('An error has occurred.')
Это означает, что поведение Response
по умолчанию было переопределено для учета кода состояния при определении истинного значения объекта.
Имейте в виду, что этот метод не проверяет, равен ли код состояния 200
. Причина этого заключается в том, что другие коды статуса в пределах 200
до 400
диапазона, таких как 204 NO CONTENT
и 304 NOT MODIFIED
, также считается успешным в том смысле , что они обеспечивают осуществимый ответ.
Например, команда 204
сообщает вам, что ответ был успешным, но в теле сообщения нет содержимого для возврата.
Поэтому убедитесь, что вы используете этот удобный способ записи, только если вы хотите узнать, был ли запрос в целом успешным, а затем, при необходимости, обработать ответ соответствующим образом на основе кода состояния.
Допустим, вы не хотите проверять код состояния ответа в if
. Вместо этого вы хотите вызвать исключение, если запрос был неудачным. Вы можете сделать это используя .raise_for_status()
:
import requests
from requests.exceptions import HTTPError
for url in ['https://api.github.com', 'https://api.github.com/invalid']:
try:
response = requests.get(url)
# If the response was successful, no Exception will be raised
response.raise_for_status()
except HTTPError as http_err:
print(f'HTTP error occurred: {http_err}') # Python 3.6
except Exception as err:
print(f'Other error occurred: {err}') # Python 3.6
else:
print('Success!')
Если вы вызываете .raise_for_status()
, HTTPError
будет поднят для определенных кодов состояния. Если код состояния указывает на успешный запрос, программа продолжит работу без возникновения этого исключения.
Теперь вы много знаете о том, как обращаться с кодом состояния ответа, полученного вами с сервера. Однако, когда вы делаете GET
запрос, вы редко заботитесь только о коде состояния ответа. Обычно вы хотите увидеть больше. Далее вы увидите, как просмотреть фактические данные, отправленные сервером обратно в теле ответа.
Содержание
Ответ на GET
запрос часто содержит некоторую ценную информацию, известную как полезная нагрузка, в теле сообщения. Используя атрибуты и методы Response
, вы можете просматривать полезную нагрузку в различных форматах.
Чтобы увидеть содержание ответа bytes
, вы используете .content
:
>>> response = requests.get('https://api.github.com')
>>> response.content
b'{"current_user_url":"https://api.github.com/user","current_user_authorizations_html_url":"https://github.com/settings/connections/applications{/client_id}","authorizations_url":"https://api.github.com/authorizations","code_search_url":"https://api.github.com/search/code?q={query}{&page,per_page,sort,order}","commit_search_url":"https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}","emails_url":"https://api.github.com/user/emails","emojis_url":"https://api.github.com/emojis","events_url":"https://api.github.com/events","feeds_url":"https://api.github.com/feeds","followers_url":"https://api.github.com/user/followers","following_url":"https://api.github.com/user/following{/target}","gists_url":"https://api.github.com/gists{/gist_id}","hub_url":"https://api.github.com/hub","issue_search_url":"https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}","issues_url":"https://api.github.com/issues","keys_url":"https://api.github.com/user/keys","notifications_url":"https://api.github.com/notifications","organization_repositories_url":"https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}","organization_url":"https://api.github.com/orgs/{org}","public_gists_url":"https://api.github.com/gists/public","rate_limit_url":"https://api.github.com/rate_limit","repository_url":"https://api.github.com/repos/{owner}/{repo}","repository_search_url":"https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}","current_user_repositories_url":"https://api.github.com/user/repos{?type,page,per_page,sort}","starred_url":"https://api.github.com/user/starred{/owner}{/repo}","starred_gists_url":"https://api.github.com/gists/starred","team_url":"https://api.github.com/teams","user_url":"https://api.github.com/users/{user}","user_organizations_url":"https://api.github.com/user/orgs","user_repositories_url":"https://api.github.com/users/{user}/repos{?type,page,per_page,sort}","user_search_url":"https://api.github.com/search/users?q={query}{&page,per_page,sort,order}"}'
Хотя .content
вы получаете доступ к необработанным байтам полезной нагрузки ответа, вам часто захочется преобразовать их в строку с использованием кодировки символов, такой как UTF-8 . response
сделает это для вас, когда вы получите доступ к .text
:
>>> response.text
'{"current_user_url":"https://api.github.com/user","current_user_authorizations_html_url":"https://github.com/settings/connections/applications{/client_id}","authorizations_url":"https://api.github.com/authorizations","code_search_url":"https://api.github.com/search/code?q={query}{&page,per_page,sort,order}","commit_search_url":"https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}","emails_url":"https://api.github.com/user/emails","emojis_url":"https://api.github.com/emojis","events_url":"https://api.github.com/events","feeds_url":"https://api.github.com/feeds","followers_url":"https://api.github.com/user/followers","following_url":"https://api.github.com/user/following{/target}","gists_url":"https://api.github.com/gists{/gist_id}","hub_url":"https://api.github.com/hub","issue_search_url":"https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}","issues_url":"https://api.github.com/issues","keys_url":"https://api.github.com/user/keys","notifications_url":"https://api.github.com/notifications","organization_repositories_url":"https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}","organization_url":"https://api.github.com/orgs/{org}","public_gists_url":"https://api.github.com/gists/public","rate_limit_url":"https://api.github.com/rate_limit","repository_url":"https://api.github.com/repos/{owner}/{repo}","repository_search_url":"https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}","current_user_repositories_url":"https://api.github.com/user/repos{?type,page,per_page,sort}","starred_url":"https://api.github.com/user/starred{/owner}{/repo}","starred_gists_url":"https://api.github.com/gists/starred","team_url":"https://api.github.com/teams","user_url":"https://api.github.com/users/{user}","user_organizations_url":"https://api.github.com/user/orgs","user_repositories_url":"https://api.github.com/users/{user}/repos{?type,page,per_page,sort}","user_search_url":"https://api.github.com/search/users?q={query}{&page,per_page,sort,order}"}'
Поскольку для декодирования bytes
в str
требуется схема кодирования, requests
попытается угадать кодировку на основе заголовков ответа, если вы не укажете один из них. Вы можете предоставить явную кодиров
Когда использовать метаклассы в Python: 5 интересных вариантов использования
В статье описывается 5 способов применения метаклассов в Python. Статья подразумевает что читатель уже знает что такое метаклассы и имеет опыт их практического использования.
Оригинальная статья: Sebastian Buczyński — When to use metaclasses in Python: 5 interesting use cases
Метаклассы упоминаются среди самых продвинутых возможностей Python. Знание того, как их использовать, воспринимается коллегами как наличие черного пояса Python. Но полезны ли они для всех собеседований или конференций? Давай выясним! Эта статья покажет вам 5 практических применений метаклассов. Заинтересованы в хорошем коде и еще лучших тестах? Обратите внимание на мою будущую книгу по архитектуре — Implementing the Clean Architecture..
Что такое метаклассы — короткий обзор
Предполагая, что вы знаете разницу между классами и объектами, тогда метаклассы не должны быть такими сложными — если кратко то они являются классами для классов (отсюда и «мета» в их названии).
Проще говоря, в то время как классы являются чертежами для объектов, метаклассы являются чертежами для классов. Класс является описанием, когда мы создаем его экземпляр, тогда как метакласс является описанием класса, и существует только когда определен класс.
Самая простая реализация метакласса, которая ничего не делает, выглядит следующим образом:
class MyMeta(type): def __new__(cls, name, bases, namespace): # cls - MyMeta # name - имя определяемого класса (MyClass в этом примере) # bases - базовые классы для построенного класса # namespace - словарь определенных в класса методов и полей # в нашем случае - {'x': 3} # super().__new__ просто возвращает новый класс return super().__new__(cls, name, bases, namespace) class MyClass(metaclass=MyMeta): x = 3
1. Избегание повторения декораторов или декорирование всех подклассов
Допустим, вы влюбились в относительно недавний модуль stdlib для dataclasses или используете более продвинутый attrs. Или вы просто используете много повторяющихся декораторов на ваших классах:
@attr.s(frozen=True, auto_attribs=True) class Event: created_at: datetime @attr.s(frozen=True, auto_attribs=True) class InvoiceIssued(Event): invoice_uuid: UUID customer_uuid: UUID total_amount: Decimal total_amount_currency: Currency due_date: datetime @attr.s(frozen=True, auto_attribs=True) class InvoiceOverdue(Event): invoice_uuid: UUID customer_uuid: UUID
Возможно, это не слишком много повторений, но мы все же можем от них избавиться, для этого напишем метакласс для Event:
class EventMeta(type): def __new__(cls, name, bases, namespace): new_cls = super().__new__(cls, name, bases, namespace) return attr.s(frozen=True, auto_attribs=True)(new_cls) # (!) class Event(metaclass=EventMeta): created_at: datetime class InvoiceIssued(Event): invoice_uuid: UUID customer_uuid: UUID total_amount: Decimal total_amount_currency: Currency due_date: datetime class InvoiceOverdue(Event): invoice_uuid: UUID customer_uuid: UUID
Самая важная строка attr.s (frozen = True, auto_attribs = True) (new_cls) она имеет дело с декоратором наших подклассов. Ключом к пониманию этого примера является тот факт, что синтаксис с «at sign» (@) является просто синтаксическим сахаром над такой конструкцией:
class Event: created_at: datetime Event = attr.s(frozen=True, auto_attribs=True)(Event)
2. Валидация подклассов
Говоря о классах, давайте подумаем о наследовании в контексте Template Method design pattern. Проще говоря, мы определяем алгоритм в базовом классе, но мы оставляем один или несколько шагов (или атрибутов) в качестве абстрактных методов (или свойств) для переопределения в подклассе. Рассмотрим этот пример:
class JsonExporter(abc.ABC): def export(self): # тут какая нибудь полезная логика with open(self._filename) as f: for row in self._build_row_from_raw_data(): pass # do some other stuff @abc.abstractmethod @property def _filename(self): pass @abc.abstractmethod def _build_row_from_raw_data(self, raw_data): pass class InvoicesExporter(JsonExporter): _filename = 'invoices.json' def _build_row_from_raw_data(self, raw_data): return {'invoice_uuid': raw_data[0]}
У нас есть простой базовый класс JsonExporter. Достаточно создать его подкласс и предоставить реализацию для свойства _filename и метода _build_row_from_raw_data. Тем не менее, abc обеспечивает проверку только на отсутствие этих параметров. Если мы, например, хотели бы проверить больше вещей, таких как уникальность имен файлов или их правильность (например, всегда заканчивается на .json), мы также можем написать метакласс для этого:
import inspect """ Мы наследуем метакласс abc (ABCMeta), чтобы избежать конфликтов метаклассов """ class JsonExporterMeta(abc.ABCMeta): _filenames = set() def __new__(cls, name, bases, namespace): # сначала выполнить логику abc new_cls = super().__new__(cls, name, bases, namespace) """ Нет необходимости запускать проверки для абстрактного класса """ if inspect.isabstract(new_cls): # 2 return new_cls """ Проверяем, является _filename строкой """ if not isinstance(namespace['_filename'], str): raise TypeError(f'_filename attribute of {name} class has to be string!') """ Проверяем, имеет ли _filename расширение .json """ if not namespace['_filename'].endswith('.json'): raise ValueError(f'_filename attribute of {name} class has to end with ".json"!') """ Проверяем уникальность _filename среди других подклассов. """ if namespace['_filename'] in cls._filenames: raise ValueError(f'_filename attribute of {name} class is not unique!') cls._filenames.add(namespace['_filename']) return new_cls """ Теперь мы не будем наследовать от abc.ABC, вместо этого будем использовать наш новый метакласс """ class JsonExporter(metaclass=JsonExporterMeta): pass # The rest of the class remains unchanged, so I skipped it class BadExporter(JsonExporter): _filename = 0x1233 # That's going to fail one of the checks def _build_row_from_raw_data(self, raw_data): return {'invoice_uuid': raw_data[0]}
Говоря о ABC, это еще одна вещь, которая реализована с использованием метаклассов. Смотрите доклад Леонардо Джордани — Abstract Base Classes: a smart use of metaclasses.
3. Регистрация подклассов — расширяемый шаблон стратегии
Используя атрибуты метаклассов, мы также можем написать умную, открытую-закрытую реализацию фабрики. Идея будет основана на ведении реестра конкретных (неабстрактных) подклассов и построении их с использованием имени:
class StrategyMeta(abc.ABCMeta): """ Храним отображение внешне используемых имен в классы. """ registry: Dict[str, 'Strategy'] = {} def __new__(cls, name, bases, namespace): new_cls = super().__new__(cls, name, bases, namespace) """ Регистрируем каждый класс """ if not inspect.isabstract(new_cls): cls.registry[new_cls.name] = new_cls return new_cls class Strategy(metaclass=StrategyMeta): @property @abc.abstractmethod def name(self): pass @abc.abstractmethod def validate_credentials(self, login: str, password: str) -> bool: pass @classmethod def for_name(cls, name: str) -> 'Strategy': """ Используем реестр для создания новых классов """ return StrategyMeta.registry[name]() class AlwaysOk(Strategy): name = 'always_ok' def validate_credentials(self, login: str, password: str) -> bool: # Imma YESman! return True # Пример использования Strategy.for_name('always_ok').validate_credentials('john', 'x')
Предупреждение: чтобы это работало, нам нужно импортировать все подклассы. Если они не будут загружены в память, они не будут зарегистрированы.
Менее абстрактным примером может быть система плагинов для линтера (подумайте о Pylint или flake8). Подклассифицируя абстрактный класс Plugin, мы будем не только предоставлять наши пользовательские проверки, но и регистрировать плагин. Кстати, если вы ищете, как написать такой плагин для Pylint — посмотрите мою статью Writing custom checkers for Pylint.
4. Декларативный способ построения GUI
Признательность за это замечательное приложение метаклассов достается Андерсу Хаммарквисту — автору EuroPython talk Metaclasses for fun and profit: Making a declarative GUI implementation.
По сути, идея состоит в том, чтобы превратить императивный код, ответственный за создание GUI из компонентов…
class MyWindow(Gtk.Window): def __init__(self): super().__init__(self, title="Hello, window!") self.box = Gtk.VBox() self.add(self.box) self.label = GtkLabel(label="Hello, label!") self.box.add(self.label)
… в это:
class Top(Window): title = "Hello, window!" class Group(VBox): class Title(Label): label = '"Hello, label!"'
Просто вау. Это впечатляет, потому что не только упрощает полученный код, но и намного лучше подходит для наших целей. Визуальная композиция с помощью вложенных классов выглядит для нас более естественно, учитывая, что конечный результат очень похож — компоненты, вложенные друг в друга.
Если вас интересуют детали реализации (и проблемы, с которыми пришлось столкнуться автору), смотрите доклад. Код доступен на bitbucket: https://bitbucket.org/iko/ep2016-declarative-gui/
5. Добавление атрибутов — Django ORM Model.DoesNotExist
Если у вас есть некоторый опыт работы с Django, вы наверняка заметили, что каждому классу модели присваивается исключение DidNotExist. Последний является атрибутом класса. Но откуда это берется? Ну, Django использует метаклассы. Для моделей они делает много вещей от проверки до динамического добавления нескольких атрибутов, таких как исключения DoesNotExist и MultipleObjectsReturned.
# django/db/models/base.py:128 if not abstract: new_class.add_to_class( 'DoesNotExist', subclass_exception( 'DoesNotExist', tuple( x.DoesNotExist for x in parents if hasattr(x, '_meta') and not x._meta.abstract ) or (ObjectDoesNotExist,), module, attached_to=new_class)) new_class.add_to_class( 'MultipleObjectsReturned', subclass_exception( 'MultipleObjectsReturned', tuple( x.MultipleObjectsReturned for x in parents if hasattr(x, '_meta') and not x._meta.abstract ) or (MultipleObjectsReturned,), module, attached_to=new_class))
Заметка о __init_subclass__
Как вы заметили, метаклассы довольно многословны. Например, если мы хотим повлиять на всю иерархию классов, нам нужно как минимум два класса (метакласс, и базовый класс).
Существует также риск попадания в конфликт метаклассов, если мы попытаемся применить его в середине иерархии. Например, вы не сможете просто использовать собственный метакласс для своей модели Django. Вы должны будете использовать трюк, — создать подкласс django.db.models.Model (django.db.models.base.ModelBase), и написать свою собственную логику в __new__, а затем создать свой собственный базовый класс для всех моделей вместо использования django.db.models.Model. Похоже, что нужно сделать много работы.
К счастью для нас, начиная с Python3.6, есть еще один доступный хук: __init_subclass__. Он может заменить большинство (если не все) метаклассы.
class Strategy(abc.ABC): _registry: Dict[str, 'Strategy'] = {} def __init_subclass__(cls, **kwargs): """ Это неявный метод класса. Он будет вызываться только для классов ниже по иерархии, а не для Strategy. """ super().__init_subclass__(**kwargs) Strategy._registry[cls.name] = cls @property @abc.abstractmethod def name(self): pass @abc.abstractmethod def validate_credentials(self, login: str, password: str) -> bool: pass @classmethod def for_name(cls, name: str) -> 'Strategy': return StrategyMeta.registry[name]() class AlwaysOk(Strategy): name = 'always_ok' def validate_credentials(self, login: str, password: str) -> bool: return True # Использование Strategy.for_name('always_ok').validate_credentials('john', 'x')
Подробнее, смотри PEP 487.
Заключение
Я знаю, о чем вы думаете — всем известно выражение что все эти метаклассы полезны, только если вы пишете свой фреймворк. В какой то мере это правильно, но если вы обнаружите в своем проекте повторяющийся шаблон кода, почему бы не подумать о метаклассах?
Часть «мета» — ключ к тому, чтобы увидеть их полезность. Когда вы видите, что тратите много времени или совершаете ошибки, выполняя «работу», возможно, есть место для некоторой «метаработы»!
Метаклассы могут быть использованы для обеспечения соблюдения соглашений, управления реализацией или обеспечения легкого расширения.
Знаете ли вы еще какое-нибудь классное приложение метаклассов? Поделитесь ими в комментариях! (В блоге автора статьи)
Была ли вам полезна эта статья?
[2 / 5]
Python-блог: Python 201: Введение в distutils (Перевод)
В прошлый раз мы узнали как создавать модули и пакеты. Сегодня мы возьмём этот пакет и посмотрим, как при помощи distutils мы можем сделать этот пакет доступным для других людей. Мы научимся:
- создавать файл setup.py
- создавать source distribution
- создавать установщик для Windows
Начнём!
Пишем наш первый скрипт “setup.py”
Когда вы пишете ваш скрипт setup.py, Вы должны держать в голове его расположение. Если он будет находиться в папке с вашим пакетом, то это приведёт к ошибке при попытке им воспользоваться. Если он будет расположен где-то далеко, то скорее всего Вы при установке добавите ещё и те файлы, которые бы распространять не хотели. Поэтому для простоты мы создадим новую папку, куда и скопируем созданную вчера папку “mymath”. И тут же сохраним наш setup.py. Структура новой папки будет выглядеть так:
myNewFolder/ mymath/ setup.py
Внимание: Если у Вас нет кода, созданного в прошлой статье, его можно скачать тут
Теперь неплохо бы этот файл наполнить кодом:
from distutils.core import setup setup(name = "mymath", version = "0.1", description = "A Simple Math Package", author = "Mike Driscoll", author_email = "[email protected]", url = "http://www.blog.pythonlibrary.org/2012/07/08/python-201-creating-modules-and-packages/", packages=["mymath"] )
Что же, выглядит не плохо. Если мы хотим добавить в наш setup.py ещё какие-то пакеты, то мы просто перечисляем их в списке packages. Кроме того есть список py_modules, куда можно добавить отдельные модули. Если Вы будете рыться в документации, то Вы обнаружите, что Вы можете добавлять даже файлы, не являющиеся скриптами Python используя класс Extension библиотеки distutils. Например, это может понадобиться для добавления файлов С или чего-то в этом роде, что можно встретить в сторонних пакетах, вроде lxml.
Distutils: Как распространять исходники и установщики для Windows
После того, как мы сохранили наш файл со скриптом, мы можем создать архив с исходниками, который будет использован для распространения нашего замечательного пакета. Откройте терминал (или командную строку в Windows) и перейдите в созданную вами папку. Затем выполните следующую команду
python setup.py sdist
Вы увидите что-то вроде этого:
C:\Users\mdriscoll\Documents\mymath-setup>python setup.py sdist
running sdist
warning: sdist: manifest template ‘MANIFEST.in’ does not exist (using default file list)
writing manifest file ‘MANIFEST’
creating mymath-0.1
creating mymath-0.1\mymath
copying files to mymath-0.1…
copying README.txt -> mymath-0.1
copying setup.py -> mymath-0.1
copying mymath\__init__.py -> mymath-0.1\mymath
copying mymath\add.py -> mymath-0.1\mymath
copying mymath\divide.py -> mymath-0.1\mymath
copying mymath\multiply.py -> mymath-0.1\mymath
copying mymath\subtract.py -> mymath-0.1\mymath
creating dist
creating ‘dist\mymath-0.1.zip’ and adding ‘mymath-0.1’ to it
adding ‘mymath-0.1\PKG-INFO’
adding ‘mymath-0.1\README.txt’
adding ‘mymath-0.1\setup.py’
adding ‘mymath-0.1\mymath\add.py’
adding ‘mymath-0.1\mymath\divide.py’
adding ‘mymath-0.1\mymath\multiply.py’
adding ‘mymath-0.1\mymath\subtract.py’
adding ‘mymath-0.1\mymath\__init__.py’
creating ‘dist\mymath-0.1.zip’ and adding ‘mymath-0.1’ to it
adding ‘mymath-0.1\PKG-INFO’
adding ‘mymath-0.1\README.txt’
adding ‘mymath-0.1\setup.py’
adding ‘mymath-0.1\mymath\add.py’
adding ‘mymath-0.1\mymath\divide.py’
adding ‘mymath-0.1\mymath\multiply.py’
adding ‘mymath-0.1\mymath\subtract.py’
adding ‘mymath-0.1\mymath\__init__.py’
removing ‘mymath-0.1’ (and everything under it)
Что бы всё это могло значить? Только то, что distutils создал новую папку, названную dist, в которой теперь находится zip файл (mymath-0.1.zip) со всеми файлами вашего пакета. Если же Вы работаете на *nix — то получите tarball.
Далее, если Вы хотите создать установщик под Windows — это тоже будет легко сделать. Вам для этого понадобится такая команда:
python setup.py bdist_wininst
Эта команда создаст папку build (на которую Вы можете не обращать внимание) и файл с названием mymath-0.1.win32.exe в вашей папке dist, который Вы можете запустить под Windows для установки вашего пакета. Так давайте попробуем!
Как установить ваш пакет?
В случае исходников, Вам надо их распаковать / разархивировать и затем выполнить следующую команду:
C:\Users\mdriscoll\Documents\mymath-setup>python setup.py sdist
running sdist
warning: sdist: manifest template ‘MANIFEST.in’ does not exist (using default file list)
writing manifest file ‘MANIFEST’
creating mymath-0.1
creating mymath-0.1\mymath
copying files to mymath-0.1…
copying README.txt -> mymath-0.1
copying setup.py -> mymath-0.1
copying mymath\__init__.py -> mymath-0.1\mymath
copying mymath\add.py -> mymath-0.1\mymath
copying mymath\divide.py -> mymath-0.1\mymath
copying mymath\multiply.py -> mymath-0.1\mymath
copying mymath\subtract.py -> mymath-0.1\mymath
creating dist
creating ‘dist\mymath-0.1.zip’ and adding ‘mymath-0.1’ to it
adding ‘mymath-0.1\PKG-INFO’
adding ‘mymath-0.1\README.txt’
adding ‘mymath-0.1\setup.py’
adding ‘mymath-0.1\mymath\add.py’
adding ‘mymath-0.1\mymath\divide.py’
adding ‘mymath-0.1\mymath\multiply.py’
adding ‘mymath-0.1\mymath\subtract.py’
adding ‘mymath-0.1\mymath\__init__.py’
creating ‘dist\mymath-0.1.zip’ and adding ‘mymath-0.1’ to it
adding ‘mymath-0.1\PKG-INFO’
adding ‘mymath-0.1\README.txt’
adding ‘mymath-0.1\setup.py’
adding ‘mymath-0.1\mymath\add.py’
adding ‘mymath-0.1\mymath\divide.py’
adding ‘mymath-0.1\mymath\multiply.py’
adding ‘mymath-0.1\mymath\subtract.py’
adding ‘mymath-0.1\mymath\__init__.py’
removing ‘mymath-0.1’ (and everything under it)
Как установить ваш пакет?
Если всё было сделано верно и всё работает верно, то пакет будет установлен в вашей системе (для той версии python, которую Вы используете для запуска этой команды — прим. пер.). Если Вы запустите установщик Windows, то возникнет такой мастер установки:
Обратите внимание, что тут показаны все метаданные, которые мы указывали в нашем скрипте setup.py. Круто, правда? В любом случае, если Вы выполните все шаги мастера — Вы опять же установите пакет на свою систему.
Внимание: при такой установке пакет будет установлен в вашу основную версию Python. Если Вы не хотите этого — используйте virtualenv.
Итоги
Теперь Вы должны уметь создавать установщики и устанавливать свои пакеты при помощи distutils. Если Вы хотите загрузить ваш пакет в Python Packages Index (PyPI) — смотрите руководство. Удачи и кодируйте удовольствие!
Чтение на будущее
Источник
модуль | __doc__ | строка документации | |
__ файл__ | имя файла (отсутствует для | ||
класс | __doc__ | строка документации | |
__модуль__ | наименование модуля, в котором | ||
метод | __doc__ | строка документации | |
__name__ | наименование, с которым это | ||
im_class | объект класса, который запросил | (1) | |
im_func или | функциональный объект | ||
сам или | инстанс, которому это | ||
функция | __doc__ | строка документации | |
__name__ | наименование, с которым это | ||
func_code | объект кода, содержащий | ||
func_defaults | кортеж любого значения по умолчанию | ||
func_doc | (то же, что __doc__) | ||
func_globals | глобальное пространство имен, в котором | ||
имя_функции | (то же, что __name__) | ||
генератор | __iter__ | определено для поддержки | |
закрыть | поднимает новый GeneratorExit | ||
gi_code | код объекта | ||
gi_frame | объект кадра или возможно | ||
gi_running | устанавливается на 1, когда генератор | ||
следующая | вернуть следующий товар из | ||
отправить | возобновляет работу генератора и | ||
бросок | используется для поднятия | ||
трассировка | tb_frame | объект кадра в этом | |
тб_ласти | индекс последней попытки | ||
тб_линено | номер текущей строки в | ||
tb_next | следующая внутренняя трассировка | ||
рама | ф_бэк | объект следующего внешнего кадра | |
f_builtins | Видно встроенных пространств имен | ||
f_code | код объекта, являющегося | ||
f_exc_traceback | трассировка, если возникла в | ||
f_exc_type | тип исключения, если возник | ||
f_exc_value | значение исключения, если возникло | ||
f_globals | глобальное пространство имен, видимое | ||
ф_ласти | индекс последней попытки | ||
f_lineno | номер текущей строки в | ||
f_locals | локальное пространство имен, видимое | ||
f_restricted | 0 или 1, если кадр находится в | ||
f_trace | функция отслеживания для этого | ||
код | co_argcount | количество аргументов (не | |
co_code | строка сырого скомпилированного | ||
co_consts | набор используемых констант | ||
co_filename | имя файла, в котором | ||
co_firstlineno | номер первой строки в | ||
co_flags | растровое изображение: 1 = оптимизировано | ||
co_lnotab | закодированное отображение строки | ||
co_name | имя, с которым этот код | ||
совместных имен | кортеж имён местных | ||
co_nlocals | количество локальных переменных | ||
co_stacksize | стек виртуальных машин | ||
co_varnames | кортеж имен | ||
встроенный | __doc__ | строка документации | |
__name__ | оригинальное название этого | ||
__self__ | инстанс, к которому |
Python inspect module — JournalDev
Python inspect module
Python inspect
module — очень полезный модуль, который используется для интроспекции живых объектов в программе и просмотра исходного кода используемых модулей, классов и функций на протяжении всей программы.Это мощно, потому что этот модуль фактически может использоваться для извлечения исходного кода самой функции, анализа аргументов, которые эта функция принимает, и связанной документации библиотеки.
Предоставление образца модуля
Чтобы взять образец, который будет использоваться на протяжении этого урока, мы создадим очень маленький образец модуля с некоторыми функциями, классами и строками документации Python. Вот фрагмент кода для sample.py
:
def module_funct (arg1, arg2 = 'default', * args):
"" "Это функция уровня модуля."" "
local_var = arg1 * 3
вернуть local_var
класс X (объект):
"" "Определение класса X" ""
def __init __ (я, имя):
self.name = имя
def get_name (self):
«Возвращает имя экземпляра».
вернуть self.name
x_obj = X ('образец_экземпляр')
класс Y (X):
"" "Это класс Y,
ребенок X класса.
"" "
# Этот метод не является частью класса X.
def do_something (сам):
"" "Здесь можно сделать все, что угодно" ""
def get_name (self):
«Заменяет версию из X»
вернуть 'Y (' + self.имя + ')'
Теперь, когда у нас есть образец модуля, готовый к использованию, мы можем начать извлекать и анализировать его исходный код, строку документации и детали объекта. Давайте начнем.
Модуль самоанализа
Давайте начнем с самоанализа определенного нами модуля-примера. Обратите внимание, что для этого у нас есть файл образца модуля sample.py
в том же каталоге, в котором мы выполняем наши сценарии. Вот фрагмент кода примера того, как мы можем проверить наш модуль:
импортная инспекция
импортный образец
для имени, данные в инспекте.getmembers (образец):
если name.startswith ('__'):
Продолжать
print ('{}: {! r}'. формат (имя, данные))
Давайте посмотрим на результат этой программы:
Модуль самоанализа с инспекцией
Анализ классов в модуле
Мы можем получить все классы, которые присутствуют в модуле, и предпринять действия, когда найдем искомый класс для:
импортная инспекция
импортный образец
для ключа данные в inspect.getmembers (sample, inspect.isclass):
print ('{}: {! r}'. формат (ключ, данные))
Давайте посмотрим на результат этой программы:
Анализ классов модулей с помощью inspect
Путем простой идентификации с помощью свойства isclass
мы смогли получить классы модулей.
Изучение методов в классе
На этот раз мы пойдем глубже, проверив методы, присутствующие в классе. Обратите внимание, что мы используем тот же метод getmembers
, но отличается только идентификатор свойства, т.е.е. - функция
:
импортная инспекция
из pprint импорт pprint
импортный образец
pprint (inspect.getmembers (sample.X, inspect.isfunction))
Давайте посмотрим на результат этой программы:
Методы самоанализа класса
Самоанализ объектов класса
С помощью модуля инспекции можно отслеживать все экземпляры класса, созданные в программа просто с помощью одного вызова функции:
импортная инспекция
из pprint импорт pprint
импортный образец
x = образец.X (имя = 'inspect_getmembers')
pprint (inspect.getmembers (x, inspect.ismethod))
Давайте посмотрим на результат этой программы:
Проверка объектов класса
Получение строки документации для класса
Модуль проверки
часто используется в инструментах Python, которые автоматизируют процесс извлечения классов и их строк документации методов, которые могут быть представлены конечным пользователям. Это означает, что разработчик может просто поместить строки документации в метод, и ту же строку документации можно использовать для представления другому разработчику приложения, что сокращает усилия разработчика:
импортная инспекция
импортный образец
print ('X.__doc__: ')
печать (образец.X .__ doc__)
Распечатать()
print ('getdoc (X):')
печать (inspect.getdoc (sample.X))
Давайте посмотрим на результат этой программы:
Получение исходного кода класса
В интеллектуальных средах, таких как IDE, модуль проверки используется для представления исходного кода модулей, классов и функций:
импортная инспекция
импортный образец
печать (inspect.getsource (sample.Y))
Давайте посмотрим на результат этой программы:
Получение исходного кода класса
Полный исходный код класса был напечатан для класса без какой-либо строки документации .
Получение исходного кода метода
На этот раз мы получаем исходный код только одного метода:
импортная инспекция
импортный образец
печать (inspect.getsource (sample.Y.get_name))
Давайте посмотрим на результат этой программы:
Получение исходного кода метода
Получение сигнатуры метода
В качестве последнего примера мы получим подпись метода, который часто используется в Intellisense. IDE, чтобы представить разработчикам, какие аргументы принимает метод:
импортная инспекция
импортный образец
печать (осмотреть.подпись (sample.module_funct))
Давайте посмотрим на результат этой программы:
Получение подписи метода
Заключение
В этом уроке мы изучили отличный модуль Python, который часто используется в инструментах кода, таких как IDE и инструменты документации, например Что ж.
Ссылка: API Doc.
27,13. inspect — проверка живых объектов — документация IronPython 2.7.2b1
IronPython
- Что нового в Python
- Что нового в Python 2.7
- Что нового в Python 2.6
- Что нового в Python 2.5
- Что нового в Python 2.4
- Что нового в Python 2.3
- Что нового в Python 2.2
- Что нового в Python 2.1
- Что нового в Python 2.0
- Учебник Python
- 1. Разжигание аппетита
- 2. Использование интерпретатора Python
- 3. Неформальное введение в Python
- 4. Дополнительные инструменты управления потоком
- 5.Структуры данных
- 6. Модули
- 7. Вход и выход
- 8. Ошибки и исключения
- 9. Классы
- 10. Краткий обзор стандартной библиотеки
- 11. Краткий обзор стандартной библиотеки — часть II
- 12. Что теперь?
- 13. Интерактивное редактирование ввода и подстановка истории
- 14. Арифметика с плавающей запятой: проблемы и ограничения
- Установка и использование Python
- 1. Командная строка и среда
- 2.Использование Python на платформах Unix
- 3. Использование Python в Windows
- 4. Использование Python на Macintosh
- Справочник по языку Python
- 1. Введение
- 2. Лексический анализ
- 3. Модель данных
- 4. Исполнение модели
- 5. Выражения
- 6. Простые утверждения
- 7. Сложные ведомости
- 8. Компоненты верхнего уровня
- 9. Полная спецификация грамматики
- Стандартная библиотека Python
- 1.Введение
- 2. Встроенные функции
- 3. Несущественные встроенные функции
- 4. Встроенные константы
- 5. Встроенные типы
- 6. Встроенные исключения
- 7. Строковые службы
- 8. Типы данных
- 9. Числовые и математические модули
- 10. Доступ к файлам и каталогам
- 11. Постоянство данных
- 12. Сжатие и архивирование данных
- 13. Форматы файлов
- 14. Криптографические службы
- 15.Общие службы операционной системы
- 16. Дополнительные службы операционной системы
- 17. Межпроцессное взаимодействие и создание сетей
- 18. Обработка данных в Интернете
- 19. Инструменты обработки структурированной разметки
- 20. Интернет-протоколы и поддержка
- 21. Мультимедийные службы
- 22. Интернационализация
- 23. Программные рамки
- 24. Графические интерфейсы пользователя с Tk
- 25. Инструменты разработки
- 26.Отладка и профилирование
- 27. Службы времени выполнения Python
- 28. Пользовательские интерпретаторы Python
- 29. Ограниченное исполнение
- 30. Импорт модулей
- 31. Службы языка Python
- 32. Пакет компилятора Python
- 33. Разные услуги
- 34. Специальные службы MS Windows
- 35. Специальные службы Unix
- 36. Специальные службы Mac OS X
- 37. Модули MacPython OSA
- 38.Специализированные службы SGI IRIX
- 39. Специальные службы SunOS
- 40. Недокументированные модули
- Расширение и встраивание интерпретатора Python
- 1. Расширение Python с помощью C или C ++
- 2. Определение новых типов
- 3. Создание расширений C и C ++ с помощью distutils
- 4. Создание расширений C и C ++ в Windows
- 5. Встраивание Python в другое приложение
- Справочное руководство по IronPython .NET API
- 1.Расширение IronPython с помощью C #
- 2. Анализ и токенизация
- Распространение модулей Python
- 1. Введение в Distutils
- 2. Написание сценария установки
- 3. Запись файла конфигурации установки
- 4. Создание дистрибутива исходного кода
- 5. Создание встроенных дистрибутивов
- 6. Регистрация в индексе пакетов
- 7. Загрузка пакетов в индекс пакетов
- 8. Примеры
- 9.Расширение Distutils
- 10. Справочник команд
- 11. Справочник по API
- Установка модулей Python
- Введение
Работа с ячейками кода Jupyter в интерактивном окне Python
Jupyter (ранее IPython Notebook) — это проект с открытым исходным кодом, который позволяет легко комбинировать текст Markdown и исполняемый исходный код Python на одном холсте, который называется записной книжкой . Visual Studio Code поддерживает работу с Jupyter Notebooks изначально, а также через файлы кода Python.В этом разделе рассматривается поддержка, предлагаемая через файлы кода Python, и показано, как:
- Работа с ячейками кода, подобными Jupyter
- Выполнить код в интерактивном окне Python
- Просмотр, проверка и фильтрация переменных с помощью проводника переменных и средства просмотра данных
- Подключение к удаленному серверу Jupyter
- Отладка ноутбука Jupyter
- Экспорт записной книжки Jupyter
Для работы с записными книжками Jupyter необходимо активировать среду Anaconda в VS Code или другую среду Python, в которой вы установили пакет Jupyter.Чтобы выбрать среду, используйте команду Python: выберите интерпретатор из палитры команд (⇧⌘P (Windows, Linux Ctrl + Shift + P)).
После активации соответствующей среды вы можете создавать и запускать ячейки кода, подобные Jupyter, подключаться к удаленному серверу Jupyter для запуска ячеек кода и экспортировать файлы Python как записные книжки Jupyter.
код Jupyter ячеек
Вы определяете ячейки кода, подобные Jupyter, в коде Python, используя комментарий # %%
:
# %%
msg = "Hello World"
печать (сообщение)
# %%
msg = "Привет снова"
печать (сообщение)
Примечание : Обязательно сохраните показанный выше код в файле с расширением.py расширение.
Когда расширение Python обнаруживает ячейку кода, оно добавляет украшения Run Cell и Debug Cell CodeLens. Первая ячейка также включает Выполнить ниже , а все последующие ячейки включают Выполнить выше :
Примечание: По умолчанию Debug Cell просто вводит код пользователя. Если вы хотите перейти в непользовательский код, вам нужно снять флажок Data Science: Debug Just My Code в настройках расширения Python (⌘, (Windows, Linux Ctrl +,)).
Ячейка запуска применяется только к одной ячейке кода. Выполнить ниже , который появляется в первой ячейке, выполняет весь код в файле. Выполнить выше применяется ко всем ячейкам кода вплоть до ячейки с украшением, но не включая ее. Вы могли бы использовать Run Above , например, для инициализации состояния среды выполнения перед запуском этой конкретной ячейки.
При выборе команды запускается Jupyter (при необходимости, это может занять минуту), затем запускаются соответствующие ячейки в окне Python Interactive :
Вы также можете запускать ячейки кода, используя (Ctrl + Enter) или команду Python: Run Selection / Line in Python Terminal (Shift + Enter).После использования этой команды расширение Python автоматически перемещает курсор в следующую ячейку. Если вы находитесь в последней ячейке файла, расширение автоматически вставляет другой ограничитель # %%
для новой ячейки, имитируя поведение записной книжки Jupyter.
Вы также можете щелкнуть поле слева от номеров строк, чтобы установить точки останова. Затем вы можете использовать Debug Cell , чтобы запустить сеанс отладки для этой ячейки кода. Отладчик останавливает выполнение в точках останова и позволяет выполнять код по одной строке за раз и проверять переменные (подробности см. В разделе «Отладка»).
Дополнительные команды и сочетания клавиш
В следующей таблице перечислены дополнительные команды и сочетания клавиш, поддерживаемые при работе с ячейками кода.
Команда | Сочетание клавиш |
---|---|
Python: перейти к следующей ячейке | Ctrl + Alt +] |
Python: перейти к предыдущей ячейке | кбстлые (Ctrl + Alt + [) |
Python: расширить выделение по ячейке выше | кбстлые (Ctrl + Shift + Alt + [ |
Python: расширить выделение ячейкой ниже | кбстлые (Ctrl + Shift + Alt +] |
Python: перемещение выбранных ячеек вверх | кбстлые (Ctrl +; U) |
Python: переместить выделенные ячейки вниз | кбстлые (Ctrl +; D) |
RoPython: вставить ячейку выше | кбстлые (Ctrl +; A) |
Python: вставить ячейку ниже | кбстлые (Ctrl +; B) |
Python: вставить ячейку ниже позиции | кбстлые (Ctrl +; S) |
Python: удалить выбранные ячейки | кбстлые (Ctrl +; X) |
Python: изменить ячейку на код | кбстлые (Ctrl +; C) |
Python: изменить ячейку на Markdown | кбстлые (Ctrl +; M) |
Python Интерактивное окно
Окно Python Interactive , упомянутое в предыдущем разделе, может использоваться как автономная консоль с произвольным кодом (с ячейками кода или без них).Чтобы использовать окно в качестве консоли, откройте его с помощью команды Python: Показать интерактивное окно Python из палитры команд. Затем вы можете ввести код, используя Enter, чтобы перейти на новую строку, и Shift + Enter, чтобы запустить код.
Чтобы использовать окно с файлом, используйте команду Запуск текущего файла в интерактивном окне Python из палитры команд.
IntelliSense
Интерактивное окно Python имеет полную поддержку IntelliSense — дополнения кода, списки участников, краткую информацию о методах и подсказки по параметрам.В интерактивном окне Python вы можете печатать так же продуктивно, как и в редакторе кода.
Программа просмотра графиков
Программа просмотра графиков дает вам возможность глубже работать с графиками. В средстве просмотра вы можете панорамировать, масштабировать и перемещаться по графикам в текущем сеансе. Вы также можете экспортировать графики в форматы PDF, SVG и PNG.
В интерактивном окне Python дважды щелкните любой график, чтобы открыть его в средстве просмотра, или нажмите кнопку развертывания в верхнем левом углу графика.
Примечание: Интерактивное окно Python поддерживает графики отрисовки, созданные с помощью matplotlib и Altair.
Интерактивное окно Python также поддерживает Visual Studio Live Share для совместной работы в реальном времени. Live Share позволяет вам совместно редактировать и совместно отлаживать аудио, серверы, терминалы, различия, комментарии и многое другое.
Эта функция требует, чтобы расширения Live Share были установлены как на хост-компьютерах, так и на гостевых компьютерах.
Обозреватель переменных и просмотрщик данных
В интерактивном окне Python можно просматривать, проверять и фильтровать переменные в текущем сеансе Jupyter. Развернув раздел Variables после выполнения кода и ячеек, вы увидите список текущих переменных, который будет автоматически обновляться по мере использования переменных в коде.
Для получения дополнительной информации о ваших переменных вы также можете дважды щелкнуть строку или использовать кнопку Показать переменную в средстве просмотра данных , чтобы просмотреть более подробное представление переменной в средстве просмотра данных.После открытия вы можете фильтровать значения, выполняя поиск по строкам.
Примечание. Проводник переменных включен по умолчанию, но его можно отключить в настройках (Python> Наука о данных: Показать обозреватель переменных Jupyter).
Подключение к удаленному серверу Jupyter
Вы можете перенести интенсивные вычисления в блокноте Jupyter на другие компьютеры, подключившись к удаленному серверу Jupyter. После подключения ячейки кода запускаются на удаленном сервере, а не на локальном компьютере.
Для подключения к удаленному серверу Jupyter:
Запустите команду Python: укажите команду URI сервера Jupyter из палитры команд (⇧⌘P (Windows, Linux Ctrl + Shift + P)).
При появлении запроса укажите URI сервера (имя хоста) с токеном аутентификации, включенным в параметр URL-адреса
? Token =
. (Если вы запускаете сервер в терминале VS Code с включенным токеном аутентификации, URL-адрес с токеном обычно появляется в выходных данных терминала, откуда вы можете его скопировать.) В качестве альтернативы вы можете указать имя пользователя и пароль после предоставления URI.Интерактивное окно Python указывает, где выполняется код, отображая URI (который размыт на изображении ниже):
Примечание: Для дополнительной безопасности Microsoft рекомендует настроить сервер Jupyter с такими мерами безопасности, как поддержка SSL и токенов.Это помогает гарантировать, что запросы, отправленные на сервер Jupyter, проходят проверку подлинности, а соединения с удаленным сервером зашифрованы. Инструкции по обеспечению безопасности сервера портативных компьютеров см. В документации Jupyter.
Преобразование записных книжек Jupyter в файл кода Python
После активации среды с установленным Jupyter вы можете открыть файл записной книжки Jupyter ( .ipynb
) в VS Code, а затем преобразовать его в код Python. После преобразования файла вы можете запустить код, как и любой другой файл Python, а также использовать отладчик VS Code.Открытие и отладка записных книжек в VS Code — это удобный способ поиска и устранения ошибок кода, что сложно сделать непосредственно в записной книжке Jupyter.
Когда вы открываете файл записной книжки, Visual Studio Code автоматически откроет его в редакторе записной книжки. Используйте значок преобразования на панели инструментов, чтобы преобразовать файл записной книжки (.ipynb) в файл Python (.py).
Выберите значок преобразования, подождите несколько секунд, а затем VS Code откроет преобразованный блокнот в файле без названия.В файле Python ячейки записной книжки разделены комментариями # %%
; Ячейки Markdown полностью преобразуются в комментарии, которым предшествует # %% [markdown]
, и отображаются как HTML в интерактивном окне вместе с кодом и выводом, например графиками:
Примечание: При первом запуске ячеек кода в файле Python расширение Python запускает сервер Jupyter. Для запуска сервера и отображения окна Python Interactive с результатами кода может потребоваться некоторое время.
Отладка записной книжки Jupyter
Отладчик Visual Studio Code позволяет пошагово выполнять код, устанавливать точки останова, проверять состояние и анализировать проблемы. Использование отладчика — полезный способ найти и исправить проблемы в коде записной книжки.
В VS Code активируйте среду Python, в которой установлен Jupyter, как описано в начале этой статьи.
Импортируйте файл
.ipynb
записной книжки в VS Code, как описано в предыдущем разделе.(Сначала загрузите файл, если вы используете облачную среду Jupyter, такую как Azure Notebooks.)Для запуска отладчика используйте один из следующих вариантов:
- Для всей записной книжки откройте палитру команд (⇧⌘P (Windows, Linux Ctrl + Shift + P)) и выполните команду Python: отладка текущего файла в интерактивном окне Python .
- Для отдельной ячейки используйте украшение Debug Cell , которое появляется над ячейкой.Отладчик специально запускает код в этой ячейке. По умолчанию Debug Cell просто входит в пользовательский код. Если вы хотите перейти в непользовательский код, вам нужно снять флажок Data Science: Debug Just My Code в настройках расширения Python (⌘, (Windows, Linux Ctrl +,)).
Чтобы ознакомиться с общими функциями отладки VS Code, такими как проверка переменных, установка точек останова и другие действия, просмотрите отладку VS Code.
При обнаружении проблем остановите отладчик, исправьте код, сохраните файл и снова запустите отладчик.
Когда вы убедитесь, что весь ваш код правильный. Сохраните файл, затем экспортируйте записную книжку, как описано в следующем разделе. Затем вы можете загрузить записную книжку в обычную среду Jupyter.
Экспорт записной книжки Jupyter
Помимо открытия записной книжки Jupyter, вы также можете использовать одну из следующих команд из палитры команд (⇧⌘P (Windows, Linux Ctrl + Shift + P)) для экспорта содержимого из файла Python в VS Code в Jupyter. ноутбук (с моделью .расширение ipynb
).
- Python: экспорт текущего файла Python как Jupyter Notebook : создает записную книжку Jupyter из содержимого текущего файла, используя разделители
# %%
и# %% [markdown]
для указания соответствующих типов ячеек. - Python: экспорт текущего файла Python и вывод в виде записной книжки Jupyter : создает записную книжку Jupyter из содержимого текущего файла и включает вывод из ячеек кода.
- Python: Экспорт интерактивного окна Python как Jupyter Notebook : создает записную книжку Jupyter из содержимого интерактивного окна Python.
После экспорта содержимого VS Code отображает запрос, с помощью которого вы можете открыть записную книжку в браузере.
02.10.2019
【Python3】 常用 模块 —— inspect_ 三个 石头 -CSDN 博客
проверить 模块
转自
проверить 模块 官方 文档
inspect 模块 四大 功能 :
1 、 类型 检查 (проверка типа)
2 、 获取 源码 (получение исходного кода)
3 、 获取 类 和 方法 的 参数 (проверка классов и функций)
4 、 解析 堆栈 ( проверка стека интерпретатора)
学习 廖雪峰 Сеть Python 实战 时 , 主要 用到 第三 个 功能 :
总结
осмотреть.подпись (fn)
: 返回 一个inspect.Signature
类型 的 对象 , 值为 fn 这个 函数 的 所有 参数inspect.Signature
对象 的paramerters
属性 : 一个09 mappingproxy对象 , 值为 一个 有序 字典 ( Orderdict
) ;里 的
key
即为 参数 名 , str 类型
这个 的value
是 一个inspect.Parameter
类型 的inspect.Parameter
对象 的kind
属性: 一个_ParameterKind
枚举 类型 的 对象 参数 的 类型 (可变 参数 参数 ,0005
Параметр 对象 的 default
属性 : 如果 这个 有 默认 值 , 即 返回 这个 值 , 如果 没有 , 返回 一个 inspect._empty
类。
代码 :
импортная инспекция
def a (a, b = 0, * c, d, e = 1, ** f):
проходят
aa = inspect.signature (a)
print ("inspect.signature (fn) 是:% s"% aa)
print ("inspect.signature (fn) 的 类型 :% s"% (type (aa)))
печать ("\ п")
bb = aa.parameters
print ("signature.paramerters 属性 是:% s"% bb)
print ("ignature.paramerters 属性 的 类型 是% s"% type (bb))
печать ("\ п")
для cc, dd в bb.items ():
print ("mappingproxy.items () 返回 的 两个 值 分别 是 :% s 和% s "% (cc, dd))
print ("mappingproxy.items () 返回 的 两个 值 的 类型 分别 是 :% s 和% s"% (тип (cc), type (dd)))
печать ("\ п")
ee = dd.kind
print ("Parameter.kind 属性 是:% s"% ee)
print ("Parameter.kind 属性 的 类型 是:% s"% type (ee))
печать ("\ п")
gg = dd.default
print ("Parameter.default 的 值 是:% s"% gg)
print ("Parameter.default 的 属性 是:% s"% type (gg))
печать ("\ п")
ff = inspect.Parameter.KEYWORD_ONLY
print ("inspect.Parameter.KEYWORD_ONLY 的 值 是:% s"% ff)
print ("inspect.Parameter.KEYWORD_ONLY 的 类型 是:% s"% type (ff))
输出 结果 :
осмотреть.подпись (fn) 是: (a, b = 0, * c, d, e = 1, ** f)
inspect.signature (fn) 的 类型 :
signature.paramerters 属性 是: OrderedDict ([('a', <Параметр "a">), ('b', <Параметр "b = 0">), ('c', <Параметр "* c">) , ('d', <Параметр "d">), ('e', <Параметр "e = 1">), ('f', <Параметр "** f">)])
ignature.paramerters 属性 的 类型 是 <класс 'mappingproxy'>
mappingproxy.items () 返回 的 两个 值 分别 是 : a a
mappingproxy.items () 返回 的 两个 值 的 类型 分别 是 : <класс 'str'> 和 <класс 'inspect.Parameter'>
Параметр.вид 属性 是: POSITIONAL_OR_KEYWORD
Parameter.kind 属性 的 类型 是:
Parameter.default 的 值 是: <класс 'inspect._empty'>
Parameter.default 的 属性 是: <класс 'тип'>
mappingproxy.items () 返回 的 两个 值 分别 是 : b 和 b = 0
mappingproxy.items () 返回 的 两个 值 的 类型 分别 是 : 和
Отладка в Python с использованием pytest.set_trace ()
Отладка кода в Python немного сложна при сравнении на другие языки программирования. Большинство из нас используют операторы печати в коде в нескольких местах, чтобы распечатать значения переменных и выяснить проблему.Или иногда используйте операторы time.sleep (), чтобы приостановить программу Python, чтобы проверить, что происходит в коде. Недавно мы начали отслеживать наш код с помощью pytest с Python Debugger (pdb). Основное преимущество состоит в том, что вы можете отслеживать состояние переменных, останавливать и возобновлять выполнение, устанавливать точки останова и т. Д. Этот пост позволяет понять, как использовать функции отладчика Python с параметрами pytest и вставлять операторы set_trace () в ваш код.
В этом посте используется наша test_example_form.py в качестве примера для иллюстрации различных функций трассировки PDB.
Использование pytest для запуска отладчика pdb
pytest по умолчанию поставляется с поддержкой отладчика Python и позволяет открывать приглашение pdb отладчика (через параметр командной строки) в начале теста или при сбоях теста. Вы можете использовать различные параметры команды, такие как l (список), a (аргументы), n (следующий) и т. Д., После ввода в приглашение pdb. Чтобы выйти из приглашения pdb, просто нажмите q (выход) и клавишу ENTER.
i) Войдите в подсказку PDB в начале каждого теста, используя опцию –trace
pytest --trace test_example_form.py |
pytest --trace test_example_form.py
Это вызовет отладчик Python в начале каждого теста.
Использование опции –trace в pytest
ii) В случае сбоев войдите в подсказку PDB. Это будет вызывать отладчик Python при каждой ошибке.
pytest --pdb test_example_form.py |
pytest --pdb test_example_form.py
Использование отладчика Python в коде
Мы можем использовать pdb.set_trace () или pytest.set_trace () для вызова отладчика PDB и трассировки из кода. Когда ваш код наткнется на строку с pdb.set_trace (), он начнет трассировку, и вы увидите приглашение pdb в командной строке. Вместо того, чтобы переходить через множество строк кода, вы можете просто использовать точку останова, в которой вы хотите отлаживать. Сначала выберите место в коде, где вы хотите запустить отладчик, и просто вставьте код ниже. В нашем случае мы поместили это перед методом set_name ().
импорт PDB №5.Задайте имя в форме pdb.set_trace () result_flag = test_obj.set_name (имя) |
импорт pdb
№5. Задайте имя в форме
pdb.set_trace ()
result_flag = test_obj.set_name (имя)
Сразу после выполнения этой строки отладчик Python запускает приглашение pdb и ждет инструкций пользователя о следующих шагах в интерактивном режиме. Python 3.7 имеет встроенную функцию breakpoint (), которая по умолчанию импортирует pdb и вызывает pdb.set_trace ()
Использование set_trace ()
Есть несколько команд, которые вы можете выполнить в приглашении pdb для отладки вашего кода, например, мониторинг переменных, установка точек останова, выполнение кода построчно, переход к функции и т. Д. Ниже приведены несколько команд, которые мы использовали . Мы подробно рассмотрим все эти команды в следующих разделах
.
n (next) - переход к следующей строке внутри той же функции
s (step) - переход к следующей строке в этой функции или вызываемой функции
b (break) - установка новых точек останова без изменения кода
p (print ) - вычислить и распечатать значение выражения
c (продолжить) - продолжить выполнение и остановиться только при обнаружении точки останова
unt (до) - продолжить выполнение до тех пор, пока не будет достигнута строка с номером больше текущего
q ( quit) - выйти из отладчика / выполнение
Шагните и войдите в код
Чтобы проиллюстрировать это, мы собираемся объединить команды «n» и «s».В нашем примере мы внесли несколько изменений в метод set_name () в нашем Base_Page.py. В рамках отладки мы поместили pdb.set_trace () перед вызовом этого метода в нашем тестовом сценарии, который находится в строке номер 50. Мы хотим проверить возвращаемое значение result_flag из метода set_name ().
set_trace () в тестовом сценарии
Итак, выполнение останавливается на следующей строке 51, где выполняется вызов функции. Теперь мы использовали команду «s» для перехода к функции set_name (). Короче говоря, команда n (next) выполняется до следующей строки и не останавливается, даже когда встречает вызов другой функции.Где as s (step) команда выполняет текущую строку и переходит к вызываемой функции.
Иллюстрация команд «n» и «s»
Вы увидите строку –Call– после команды «s», чтобы сообщить пользователям, что к функции был произведен вызов. Когда достигается конец функции, она печатает –Return– вместе с возвращаемым значением в конце. В нашем примере функция set_name () вернула значение «True», и это то, что мы видим в строке возврата. Если вы хотите выйти из вызываемой функции и возобновить выполнение действий, вы можете использовать команду «r» из приглашения pdb.
Продолжить выполнение
Когда вы достигли точки, когда, по вашему мнению, вам нужно прекратить отладку, вы можете использовать команду «c», чтобы продолжить выполнение. Он продолжает нормально завершать поток выполнения. Он останавливается только при достижении точки останова. Точно так же у нас есть команда «unt», которая похожа на команду «c», но принимает аргумент номера строки, если он указан, будет выполняться до тех пор, пока не достигнет номера строки, большего или равного значению аргумента.
Вычислить значения переменных и выражения
Часто возникают случаи, когда вы можете захотеть посмотреть переменную, возвращаемую функцией или методом. Вы можете добиться этого с помощью команды «p». Эта команда оценит выражение во время выполнения и распечатает его значение. В приведенном выше примере мы хотим оценить значения result_flag и case_id, мы можем использовать «p result_flag» и «p case_id», как показано ниже
.
Использование «p» для оценки и печати переменных
Установка новых точек останова без изменения кода
Вы можете использовать команду «b (reak)» для установки точки останова без изменения кода.Вы можете передать аргумент номера строки или аргумент функции, как показано ниже.
b (reak) [[имя файла:] белье | функция [, условие]] |
b (reak) [[имя файла:] белье | функция [, условие]]
Аргумент номера строки без префикса имени файла установит точку останова в текущем файле. Если аргумент номеров строк имеет префикс с именем файла, тогда точка останова будет установлена в указанном файле (файл будет найден в sys.path).Теперь посмотрим, как это работает с опцией номеров строк. В приведенном ниже примере мы устанавливаем три точки останова на разные номера строк. Мы не указали здесь имя файла, поэтому точка останова установлена в текущем файле. Каждой точке останова присваивается номер.
Установка точек останова с использованием номеров строк
Ниже приведены несколько параметров, используемых с b (reak)
i) Список всех точек останова
Список всех точек останова
ii) Включение и отключение точек останова
включить номер точки останова отключить номер точки останова |
включить номер точки останова
отключить точку останова номер
Включить и отключить точки останова
iii) Удалить точку останова в коде
Удалить точку останова
В этом посте рассматриваются несколько основных и важных команд.Есть много других команд, которые можно использовать в отладчике pdb python. Вы можете обратиться по этой ссылке для получения документации по pdb.
Список литературы
1. Использование и вызовы Pytest
2. Отладка приложений Python с помощью pdb
Я инженер с 10-летним опытом разработки и тестирования программного обеспечения. До прихода в Qxf2 я работал с такими известными компаниями, как Dell и Infosys. Они помогли мне получить хороший опыт в области производства и здравоохранения.Моя карьера QA началась в Dell. Я познакомился с различными инструментами, процессами и методологиями тестирования, получил возможность работать на различных платформах, таких как JMS Hermes, SOAP UI, интеграция данных, очереди и т. Д. Я выбрал Qxf2, потому что он позволяет удаленно работать. Мои интересы - выращивание овощей с использованием органических методов, прослушивание музыки и чтение книг.
Ищете экспертов по автоматизации контроля качества?
Нанять Qxf2. Наши эксперты по тестированию помогут вам разработать более качественное программное обеспечение.
Учить больше
.