Разное

Python colon expected: What is causing the Colon Expected Error in Python?

Содержание

16 частых ошибок начинающих программистов при выполнении скриптов (Runtime errors)

Набрел на занятную статью о частых ошибках на Python у начинающих программистов. Мне кажется, она полезна будет для тех, кто перешел с другого языка или только планирует переход. Далее идет перевод.

Поиск решения проблем с сообщениями об ошибках, выдаваемых при запуске программ в Python, может доставлять трудности, если вы изучаете этот язык программирования впервые. Далее будут описаны наиболее частые ошибки, встречающиеся при запуске программ и вызывающие сбой при выполнении.

1) Пропущено двоеточие в конце строки после управляющих конструкций типа if, elif, else, for, while, class, or def, что приведет к ошибке типа SyntaxError: invalid syntax

Пример кода:

if spam == 42
    print('Hello!')

2) Использование = вместо == приводит к ошибке типа SyntaxError: invalid syntax

Символ = является оператором присваивания, а символ == — оператором сравнения.

Эта ошибка возникает в следующем коде:

if spam = 42:
    print('Hello!')

3) Использование неправильного количества отступов.

Возникнет ошибка типа IndentationError: unexpected indent, IndentationError: unindent does not match any outer indentation level и IndentationError: expected an indented block

Нужно помнить, что отступ необходимо делать только после :, а по завершению блока обязательно вернуться к прежнему количеству отступов.

Пример ошибки:

print('Hello!')
    print('Howdy!')

и тут

if spam == 42:
    print('Hello!')
  print('Howdy!')

и тут

if spam == 42:
print('Hello!')

4) Неиспользование функции len() в объявлении цикла for для списков list

Возникнет ошибка типа TypeError: ‘list’ object cannot be interpreted as an integer

Часто возникает желание пройти в цикле по индексам элементов списка или строки, при этом требуется использовать функцию range(). Нужно помнить, что необходимо получить значение len(someList) вместо самого значения someList

Ошибка возникнет в следующем коде:

spam = ['cat', 'dog', 'mouse']
for i in range(spam):
    print(spam[i])

Некоторые читатели (оригинальной статьи) заметили, что лучше использовать конструкцию типа for i in spam:, чем написанный код выше. Но, когда нужно получить номер итерации в цикле, использование вышенаписанного кода намного полезнее, чем получение значения списка.

От переводчика: Иногда можно ошибочно перепутать метод shape с len() для определения размера списка. При этом возникает ошибка типа ‘list’ object has no attribute ‘shape’

5) Попытка изменить часть строки. (Ошибка типа TypeError: ‘str’ object does not support item assignment)

Строки имеют неизменяемый тип. Эта ошибка произойдет в следующем коде:

spam = 'I have a pet cat.'
spam[13] = 'r'
print(spam)

А ожидается такое результат:

spam = 'I have a pet cat.'
spam = spam[:13] + 'r' + spam[14:]
print(spam)

От переводчика: Подробней про неизменяемость строк можно прочитать тут

6) Попытка соединить нестроковую переменную со строкой приведет к ошибке TypeError: Can’t convert ‘int’ object to str implicitly

Такая ошибка произойдет тут:

numEggs = 12
print('I have ' + numEggs + ' eggs.')

А нужно так:

numEggs = 12
print('I have ' + str(numEggs) + ' eggs.')

или так:

numEggs = 12
print('I have %s eggs.' % (numEggs))

От переводчика: еще удобно так

print('This {1} xorosho{0}'.format('!','is'))
# This is xorosho!

7) Пропущена одинарная кавычка в начале или конце строковой переменной (Ошибка SyntaxError: EOL while scanning string literal)

Такая ошибка произойдет в следующем коде:

print(Hello!')

или в этом:

print('Hello!)

или в этом:

myName = 'Al'
print('My name is ' + myName + . How are you?')

8) Опечатка в названии переменной или функции (Ошибка типа NameError: name ‘fooba’ is not defined)

Такая ошибка может встретиться в таком коде:

foobar = 'Al'
print('My name is ' + fooba)

или в этом:

spam = ruond(4.2)

или в этом:

spam = Round(4.2)

От переводчика: очень часто при написании возникают ошибки типа NameError: name ‘true’ is not defined и NameError: name ‘false’ is not defined, связанные с тем, что нужно писать булевные значения с большой буквы True и False

9) Ошибка при обращении к методу объекта. (Ошибка типа AttributeError: ‘str’ object has no attribute ‘lowerr’)

Такая ошибка произойдет в следующем коде:

spam = 'THIS IS IN LOWERCASE.'
spam = spam.lowerr()

10) Попытка использовать индекс вне границ списка. (Ошибка типа IndexError: list index out of range)

Ошибка возникает в следующем коде:

spam = ['cat', 'dog', 'mouse']
print(spam[6])

11) Использование несуществующих ключей для словаря. (Ошибка типа KeyError: ‘spam’)

Ошибка произойдет в следующем коде:

spam = {'cat': 'Zophie', 'dog': 'Basil', 'mouse': 'Whiskers'}
print('The name of my pet zebra is ' + spam['zebra'])

12) Использование зарезервированных в питоне ключевых слов в качестве имени для переменной. (Ошибка типа SyntaxError: invalid syntax)

Ключевые слова (зарезервированные) в питоне невозможно использовать как переменные. Пример в следующем коде:

class = 'algebra'

Python 3 имеет следующие ключевые слова: and, as, assert, break, class, continue, def, del, elif, else, except, False, finally, for, from, global, if, import, in, is, lambda, None, nonlocal, not, or, pass, raise, return, True, try, while, with, yield

13) Использование операторов присваивания для новой неинициализированной переменной. (Ошибка типа NameError: name ‘foobar’ is not defined)

Не стоит надеяться, что переменные инициализируются при старте каким-нибудь значением типа 0 или пустой строкой.

Эта ошибка встречается в следующем коде:

spam = 0
spam += 42
eggs += 42

Операторы присваивания типа spam += 1 эквивалентны spam = spam + 1. Это означает, что переменная spam уже должна иметь какое-то значение до.

14) Использование локальных переменных, совпадающих по названию с глобальными переменными, в функции до инициализации локальной переменной. (Ошибка типа UnboundLocalError: local variable ‘foobar’ referenced before assignment)

Использование локальной переменной в функции с именем, совпадающим с глобальной переменной, опасно. Правило: если переменная в функции использовалась с оператором присвоения, это всегда локальная переменная для этой функции. В противном случае, это глобальная переменная внутри функции.

Это означает, что нельзя использовать глобальную переменную (с одинаковым именем как у локальной переменной) в функции до ее определения.

Код с появлением этой ошибки такой:

someVar = 42
def myFunction():
    print(someVar)
    someVar = 100
myFunction()

15) Попытка использовать range() для создания списка целых чисел. (Ошибка типа TypeError: ‘range’ object does not support item assignment)

Иногда хочется получить список целых чисел по порядку, поэтому range() кажется подходящей функцией для генерации такого списка. Тем не менее нужно помнить, что range() возвращает range object, а не список целых чисел.

Пример ошибки в следующем коде:

spam = range(10)
spam[4] = -1

Кстати, это работает в Python 2, так как range() возвращает список. Однако попытка выполнить код в Python 3 приведет к описанной ошибке.

Нужно сделать так:

spam = list(range(10))
spam[4] = -1

16) Отсутствие операторов инкремента ++ или декремента —. (Ошибка типа SyntaxError: invalid syntax)

Если вы пришли из другого языка типа C++, Java или PHP, вы можете попробовать использовать операторы ++ или — для переменных. В Питоне таких операторов нет.

Ошибка возникает в следующем коде:

spam = 0
spam++

Нужно написать так:

spam = 0
spam += 1

17) Как заметил читатель Luciano в комментариях к статье (оригинальной), также часто забывают добавлять self как первый параметр для метода. (Ошибка типа TypeError: myMethod() takes no arguments (1 given)

Эта ошибка возникает в следующем коде:

class Foo():
    def myMethod():
        print('Hello!')
a = Foo()
a.myMethod()

Краткое объяснение различных сообщений об ошибках представлено в Appendix D of the «Invent with Python» book.

Полезные материалы

Оригинал статьи

Наиболее частые проблемы Python и решения (перевод)

Вещи, о которых следует помнить, программируя на Python

Python 3 для начинающих: Часто задаваемые вопросы


Программа не работает. Что делать?

Моя программа не работает! Что делать? В данной статье я постараюсь собрать наиболее частые ошибки начинающих программировать на python 3, а также расскажу, как их исправлять.
SyntaxError: invalid syntax

Причина: Вам подсунули программу на Python 2.

Решение: Прочитать об отличиях Python 2 от Python 3. Переписать её на Python 3. Например, данная программа на Python 3 будет выглядеть так:

name = input()
print(name)

Проблема: TypeError: Can’t convert ‘int’ object to str implicitly.

Пример кода:

>>> a = input() + 5
8
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't convert 'int' object to str implicitly

Причина: Нельзя складывать строку с числом.

Решение: Привести строку к числу с помощью функции int(). Кстати, заметьте, что функция input() всегда возвращает строку!

>>> a = int(input()) + 5
8
>>> a
13

Проблема: SyntaxError: invalid syntax.

Пример кода:

a = 5
if a == 5
    print('Ура!')

Ошибка:

  File "a.py", line 3
    if a == 5
            ^
SyntaxError: invalid syntax

Причина: Забыто двоеточие.
TabError: inconsistent use of tabs and spaces in indentation

Причина: Смешение пробелов и табуляции в отступах.

Решение: Исправить отступы.

a = 10
if a > 0:
    print(a)
    print('Ура!')

Проблема: UnboundLocalError: local variable ‘a’ referenced before assignment.

Пример кода:

def f():
    a += 1
    print(a)

a = 10
f()

Ошибка:

Traceback (most recent call last):
  File "a.py", line 7, in <module>
    f()
  File "a.py", line 3, in f
    a += 1
UnboundLocalError: local variable 'a' referenced before assignment

Причина: Попытка обратиться к локальной переменной, которая ещё не создана.

Решение:

def f():
    global a
    a += 1
    print(a)

a = 10
f()

Проблема: Программа выполнилась, но в файл ничего не записалось / записалось не всё.

Пример кода:

>>> f = open('output.txt', 'w', encoding='utf-8')
>>> f.write('bla')
3
>>>

Причина: Не закрыт файл, часть данных могла остаться в буфере.

Решение:

>>> f = open('output.txt', 'w', encoding='utf-8')
>>> f.write('bla')
3
>>> f.close()
>>>

Проблема: Здесь может быть ваша проблема. Комментарии чуть ниже 🙂


Также вам может быть полезно это описание:

Как игнорировать предупреждения в Python

Я продолжаю получать это:

DeprecationWarning: integer argument expected, got float

Как я могу сделать это сообщение уйти? Есть ли способ избежать предупреждений в Python?

9 ответов


из документации warnings модуль:

 #!/usr/bin/env python -W ignore::DeprecationWarning

Если вы находитесь на Windows: pass -W ignore::DeprecationWarning в качестве аргумента в Python. Лучше, однако, решить проблему, бросив в int.

(обратите внимание, что в Python 3.2, предупреждения игнорируются по умолчанию.)

91

автор: Stephan202


у меня были такие:

/home/eddyp/virtualenv/lib/python2.6/site-packages/Twisted-8.2.0-py2.6-linux-x86_64.egg/twisted/persisted/sob.py:12:
DeprecationWarning: the md5 module is deprecated; use hashlib instead import os, md5, sys

/home/eddyp/virtualenv/lib/python2.6/site-packages/Twisted-8.2.0-py2.6-linux-x86_64.egg/twisted/python/filepath.py:12:
DeprecationWarning: the sha module is deprecated; use the hashlib module instead import sha

исправлено с помощью:

import warnings

with warnings.catch_warnings():
    warnings.filterwarnings("ignore",category=DeprecationWarning)
    import md5, sha

yourcode()

теперь вы все равно получите все другие DeprecationWarnings, но не те, которые вызваны:

import md5, sha

154

автор: Eddy Pronk


вы должны просто исправить ваш код, но на всякий случай

import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning) 

Я нашел самый чистый способ сделать это (особенно в windows), добавив следующее C:\Python26\Lib\site-packages\sitecustomize.py:

import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)

обратите внимание, что мне пришлось создать этот файл. Конечно, измените путь к python, если ваш отличается.

25

автор: Tristan Havelick


передать правильные аргументы? : P

на более серьезной ноте вы можете передать аргумент-Wi::DeprecationWarning в командной строке интерпретатору, чтобы игнорировать предупреждения об устаревании.


преобразовать аргумент в int. Это так же просто, как

int(argument)

5

автор: Gonzalo Quero


ни один из упомянутых ответов не работал для меня, поэтому я опубликую свой способ решить эту проблему. Я использую следующее at the beginning of my main.py скрипт и он работает нормально.


используйте следующее как есть (скопируйте-вставьте его):

import numpy as np
import . . . . . . . 

def warn(*args, **kwargs):
    pass
import warnings
warnings.warn = warn

# more code here...
# more code here...


Не бить вас об этом, но вас предупреждают, что то, что вы делаете, скорее всего, перестанет работать при следующем обновлении python. Преобразуйте в int и покончите с этим.

кстати. Вы также можете написать свой собственный обработчик предупреждений. Просто назначьте функцию, которая ничего не делает.
как перенаправить предупреждения python в пользовательский поток?


Если вы хотите игнорировать предупреждения только в функциях, вы можете сделать следующее.

import warnings
from functools import wraps


def ignore_warnings(f):
    @wraps(f)
    def inner(*args, **kwargs):
        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter("ignore")
            response = f(*args, **kwargs)
        return response
    return inner

@ignore_warnings
def foo(arg1, arg2):
    ...
    write your code here without warnings
    ...

@ignore_warnings
def foo2(arg1, arg2, arg3):
    ...
    write your code here without warnings
    ...

просто добавьте декоратор @ignore_warnings в функцию, которую вы хотите игнорировать все предупреждения

1

автор: Trideep Rath


Traceback в Python — Еще один блог веб-разработчика

Перевод статьи Chad Hansen : Understanding the Python Traceback

Содержание

Python отображает трассировку (traceback) при возникновении исключения в вашем коде. Содержимое трассировки может быть немного запутанным, если вы видите ее впервые или не знаете, что в она означает. Но трассировка содержит множество информации, которая может помочь вам диагностировать и устранить причину возникновения исключения.

К концу этой статьи вы сможете:

  • Лучше разбираться с содержимом трассировки (traceback)
  • Сразу узнавать некоторые из наиболее распространенных шаблонов в трассировке
  • Узнаете как правильно логировать трассировку, в то же время обрабатывая исключение

Что такое Traceback в Python?

Трассировка (Traceback) — это отчет, содержащий вызовы функций, сделанные в вашем коде в определенный момент. Трассировка известна под многими именами, включая stack trace (трассировку стека), stack traceback (трассировку стека), backtrace (обратную трассировку) и, возможно, другие. В Python используется термин traceback.

Когда ваша программа выдает исключение, Python отображает трассировку, чтобы помочь вам узнать, что пошло не так. Ниже приведен пример, иллюстрирующий эту ситуацию:

# example.py
def greet(someone):
    print('Hello, ' + someon)

greet('Chad')

Здесь вызывается функция greet() с параметром someone. Однако в greet() это имя переменной не используется. Вместо этого было ошибочно указано переменная someon в вызове print().

Примечание. В этом руководстве предполагается, что вы знаете что такое исключения в Python. Если вы незнакомы или просто хотите освежиться, то вам следует почитать Python Exceptions: Введение.

Когда вы запустите эту программу, вы получите следующий traceback:

$ python example.py
Traceback (most recent call last):
  File "/path/to/example.py", line 4, in <module>
    greet('Chad')
  File "/path/to/example.py", line 2, in greet
    print('Hello, ' + someon)
NameError: name 'someon' is not defined

Этот вывод traceback содержит всю информацию, необходимую для диагностики проблемы. Последняя строка вывода сообщает вам, какой тип исключения был сгенерирован вместе с некоторой соответствующей информацией об этом исключении. Предыдущие строки указывают на код, который привел к возникновению исключения.

В приведенной выше traceback исключением был NameError, что означает, что имеется ссылка на какое-то имя (переменная, функция, класс), которое не было определено. В нашем примере использовано имя — someon.

В последней строке в этом случае достаточно информации, чтобы помочь вам решить проблему. Поиск кода по имени someon, который является орфографической ошибкой, укажет вам правильное направление. Однако часто ваш код намного сложнее.

Как читать Traceback?

Трассировка содержит много полезной информации, когда вы пытаетесь определить причину возникновения исключения в вашем коде. В этом разделе мы рассмотрим различные варианты трассировок, чтобы понять, какая информация содержится в них.

Обзор Traceback

Есть несколько разделов в каждой трассировки, которые по своему важны. Диаграмма ниже выделяет эти части:

В Python лучше читать трассировку снизу вверх:

  1. Синяя рамка: Последняя строка трассировки является строкой сообщения об ошибке. Она содержит имя исключения, которое было вызвано.
  2. Зеленая рамка: После имени исключения появляется сообщение об ошибке. Это сообщение обычно содержит полезную информацию для понимания причины возникновения исключения.
  3. Желтая рамка: Далее по трассировке следуют различные вызовы функций, перемещающиеся снизу вверх. Эти вызовы представлены двухстрочными записями для каждого вызова. Первая строка каждого вызова содержит информацию, такую как имя файла, номер строки и имя модуля, это указывает, где можно найти код.
  4. Красная рамка: Вторая строка для этих вызовов содержит фактический код, который был выполнен.

Есть несколько различий между выводом трассировки, когда вы выполняете свой код в командной строке и выполняете код в REPL. Ниже приведен тот же код из предыдущего раздела, выполненного в REPL, и результирующий вывод трассировки:

>>> def greet(someone):
...   print('Hello, ' + someon)
... 
>>> greet('Chad')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in greet
NameError: name 'someon' is not defined

Обратите внимание, что вместо имен файлов вы получаете <stdin>. Это имеет смысл, поскольку вы вводили код с помощью стандартного ввода. Кроме того, выполненные строки кода не отображаются в трассировке.

Примечание. Если вы привыкли видеть трассировки стека в других языках программирования, вы заметите существенное различие в том, как выглядит трассировка в Python. Большинство других языков печатают исключение сверху, а затем идут сверху вниз, самые последние вызовы — наименее недавние.

Пример чтения трассировки

Просмотр некоторых конкретных результатов трассировки поможет вам лучше понять и узнать, какую информацию вам предоставит трассировка.

Приведенный ниже код используется в следующих примерах для иллюстрации информации, которую предоставляет вам трассировка:

# greetings.py
def who_to_greet(person):
    return person if person else input('Greet who? ')

def greet(someone, greeting='Hello'):
    print(greeting + ', ' + who_to_greet(someone))

def greet_many(people):
    for person in people:
        try:
            greet(person)
        except Exception:
            print('hi, ' + person)

Здесь who_to_greet() принимает значение person и либо возвращает его, либо запрашивает возвращаемое значение.

Затем greet() принимает имя, которое нужно приветствовать, someone, и необязательное значение greeting и вызывает print(). who_to_greet() также вызывается с переданным значением someone.

Наконец, greet_many() будет перебирать список people и вызывать greet(). Если при вызове greet() возникает исключение, то выводится простое резервное приветствие.

В этом коде нет ошибок, которые могли бы привести к возникновению исключения, если предоставлен правильный ввод.

Если вы добавите вызов greet() в конец файла greetings.py и укажете аргумент ключевого слова, которого он не ожидает (например, greet(‘Chad’, greting = ‘Yo’)), то вы получите следующую ошибку:

Traceback (most recent call last):
  File "/path/to/greetings.py", line 19, in <module>
    greet('Chad', greting='Yo')
TypeError: greet() got an unexpected keyword argument 'greting'

Еще раз, с трассировкой Python, лучше работать в обратном направлении, двигаясь вверх по выводу. Начиная с последней строки трассировки, вы можете видеть, что исключением является TypeError. Сообщения, которые следуют за типом исключения, все что после двоеточия, дают вам важную информацию. Оно говорит вам, что greet() был вызван с аргументом ключевого слова, которого он не ожидал. Вам также дано неизвестное имя аргумента: greting.

Двигаясь вверх, вы можете увидеть строку, которая привела к исключению. В данном случае это вызов greet(), который мы добавили в конец greetings.py.

В следующей строке вы увидите путь к файлу, в котором существует код, номер строки этого файла, в котором можно найти код, и модуль, в котором он находится. В этом случае, поскольку наш код не использует какие-либо другие модули Python мы просто видим <module> здесь, что означает, что это исполняемый файл.

С другим файлом и другим вводом вы можете увидеть, что трассировка действительно указывает вам правильное направление, чтобы найти проблему. Если вы следуете дальше, удалите глючный вызов greet() из нижней части greetings.py и добавьте новый файл example.py со следующим содержимым:

# example.py
from greetings import greet

greet(1)

В этом файле вы импортируете ваш предыдущий модуль, greetings.py, и использует из него greet(). Вот что произойдет, если вы запустите example.py:

$ python example.py
Traceback (most recent call last):
  File "/path/to/example.py", line 3, in <module>
    greet(1)
  File "/path/to/greetings.py", line 5, in greet
    print(greeting + ', ' + who_to_greet(someone))
TypeError: must be str, not int

Исключением, возникающим в этом случае, снова является TypeError, но на этот раз сообщение немного менее полезно. Он говорит вам, что где-то в коде он ожидал работать со строкой, но было дано целое число.

Двигаясь вверх, вы видите строку кода, которая была выполнена. Затем файл и номер строки кода. Однако на этот раз вместо <module> мы получаем имя функции, которая выполнялась, greet().

Переходя к следующей исполняемой строке кода, мы видим, что наш проблемный вызов greet() передается в виде целого числа.

Иногда после возникновения исключения другой фрагмент кода перехватывает это исключение что также приводит к исключению. В этих ситуациях Python выводит все трассировки исключений в том порядке, в котором они были получены, снова заканчиваясь последним вызовом трассировки исключений.

Так как это может немного сбить с толку, рассмотрим пример. Добавьте вызов greet_many() в конец greetings.py:

# greetings.py
...
greet_many(['Chad', 'Dan', 1])

Это должно привести к выводу приветствия всем трем людям. Однако, если вы запустите этот код, вы увидите пример вывода нескольких трассировок:

$ python greetings.py
Hello, Chad
Hello, Dan
Traceback (most recent call last):
  File "greetings.py", line 10, in greet_many
    greet(person)
  File "greetings.py", line 5, in greet
    print(greeting + ', ' + who_to_greet(someone))
TypeError: must be str, not int

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "greetings.py", line 14, in <module>
    greet_many(['Chad', 'Dan', 1])
  File "greetings.py", line 12, in greet_many
    print('hi, ' + person)
TypeError: must be str, not int

Обратите внимание на выделенную строку, During handling… в данных выше. Это означает что, пока ваш код пытался обработать предыдущее исключение, возникло другое исключение.

Примечание. Функция отображения обратных трассировок предыдущих исключений была добавлена в Python 3. В Python 2 вы получите только трассировку последнего исключения.

Вы видели предыдущее исключение раньше, когда вызывали greet() с целым числом. Поскольку мы добавили 1 к списку приветствующих людей, мы можем ожидать того же результата. Однако функция greet_many() упаковывает вызов greet() в блок try и except. На случай, если greet() вызывает исключение, тогда greet_many() будет выводить приветствие по умолчанию.

Еще раз повторим соответствующую часть greetings.py:

def greet_many(people):
    for person in people:
        try:
            greet(person)
        except Exception:
            print('hi, ' + person)

Поэтому, когда greet() приводит к TypeError из-за неправильного целочисленного ввода, greet_many() обрабатывает это исключение и пытается вывести простое приветствие. Здесь код заканчивается в результате другого, похожего, исключения. Он все еще пытается добавить строку и целое число.

Просмотр всех результатов трассировки может помочь вам понять, что может быть реальной причиной исключения. Иногда, когда вы видите, что последнее исключение было вызвано, и в результате получен обратный вызов, вы все равно не видите, что не так. В этих случаях переход к предыдущим исключениям обычно дает лучшее представление об основной причине.

Каковы некоторые общие трассировки в Python?

Знание того, как читать трассировку Python, когда ваша программа вызывает исключение, может быть очень полезным, когда вы программируете, но знание некоторых из наиболее распространенных трассировок также может ускорить этот процесс.

Далее рассмотрим некоторые распространенные исключения, с которыми вы можете столкнуться.

AttributeError

AttributeError вызывается, когда вы пытаетесь получить доступ к атрибуту объекта, для которого этот атрибут не определен.

Возникает при сбое ссылки на атрибут или при операции присвоения. (Источник)

Вот пример возникновения AttributeError:

>>> an_int = 1
>>> an_int.an_attribute
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute 'an_attribute'

Строка сообщения об ошибке для AttributeError говорит нам, что конкретный тип объекта, int в нашем случае, не имеет доступ к атрибуту an_attribute. Видя AttributeError в строке сообщения об ошибке, вы можете быстро определить, к какому атрибуту вы пытались получить доступ и где его исправить.

В большинстве случаев получение этого исключения означает, что вы, вероятно, работаете с объектом, который не соответствует ожидаемому типу:

>>> a_list = (1, 2)
>>> a_list.append(3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute 'append'

В приведенном выше примере вы можете ожидать, что a_list будет иметь тип list, у которого есть метод с именем .append(). Когда вы получаете исключение AttributeError и видите, что оно было сгенерировано, когда вы попытались вызвать .append(), это говорит о том, что вы, вероятно, не имеете дело с ожидаемым типом объекта.

Часто это происходит, когда вы ожидаете, что объект будет возвращен из вызова функции или метода определенного типа, а в результате вы получаете объект типа None. В этом случае строка сообщения об ошибке будет иметь следующий вид: AttributeError: ‘NoneType’ object has no attribute ‘append’.

ImportError

Ошибка ImportError возникает, когда что-то не так с оператором импорта. Вы получите это исключение или его подкласс ModuleNotFoundError, если модуль, который вы пытаетесь импортировать, не может быть найден или если вы пытаетесь импортировать что-то из модуля, который не существует в модуле.

Возникает, когда в операторе импорта возникают проблемы при попытке загрузить модуль. Также вызывается, когда в операторе from … import использовано имя модуля, которое невозможно найти. (Источник)

Вот пример возникновения ImportError и ModuleNotFoundError:

>>> import asdf
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'asdf'
>>> from collections import asdf
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: cannot import name 'asdf'

В приведенном выше примере вы можете увидеть, что попытка импортировать несуществующий модуль asdf приводит к ModuleNotFoundError. При попытке импортировать что-то, что не существует, asdf, из модуля, который существует приводит к ImportError. Строки сообщений об ошибках в нижней части трассировки показывают, какой объект неполучается импортировать. В нашем примере asdf .

IndexError

Ошибка IndexError возникает, когда вы пытаетесь получить индекс из последовательности, такой как список или кортеж, а индекс не найден в этой последовательности.

Возникает, когда текущий индекс последовательности находится вне используемого диапазона. (Источник)

Вот пример, который вызывает IndexError:

>>> a_list = ['a', 'b']
>>> a_list[3]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

Строка сообщения об ошибке для IndexError не дает вам полезной информации. Вы можете увидеть, что у вас есть ссылка на последовательность, выходящая за пределы диапазона, и тип последовательности — список в данном случае. Этой информации в сочетании с остальной частью трассировки обычно достаточно, чтобы помочь вам быстро определить, как устранить проблему.

KeyError

Подобно IndexError, KeyError вызывается, когда вы пытаетесь получить доступ к ключу, которого нет в объекте, обычно это dict. Думайте об этом как об IndexError, но для словарей.

Возникает, когда ключ набора (словарь) не найден в наборе существующих ключей. (Источник)

Вот пример возникновения KeyError:

>>> a_dict['b']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'b'

Строка сообщения об ошибке для KeyError показывает вам ключ, который не может быть найден. Это не так много, но в сочетании с остальной частью трассировки, как правило, достаточно, чтобы решить проблему.

Для более глубокого понимания KeyError, взгляните на Python KeyError Exceptions and How to Handle Them..

NameError

Ошибка NameError возникает, когда вы ссылаетесь на переменную, модуль, класс, функцию или другое имя, которое не было определено в вашем коде.

Возникает, когда локальное или глобальное имя не найдено. (Источник)

В приведенном ниже коде greet() принимает параметр person. Но в самой функции этот параметр был ошибочно указан как persn:

>>> def greet(person):
...     print(f'Hello, {persn}')
>>> greet('World')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in greet
NameError: name 'persn' is not defined

Строка сообщения об ошибке трассировки NameError дает вам имя, которое отсутствует. В приведенном выше примере это переменная или параметр с ошибкой.

NameError также будет вызываться, если использован ошибочный параметр:

>>> def greet(persn):
...     print(f'Hello, {person}')
>>> greet('World')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in greet
NameError: name 'person' is not defined

SyntaxError

Ошибка SyntaxError возникает, когда в вашем коде неверный синтаксис Python.

Возникает, когда синтаксический анализатор обнаруживает синтаксическую ошибку. (Источник)

Ниже проблема заключается в отсутствующем двоеточии, которое должно находиться в конце строки определения функции. (каретку), указывающую на проблемное место. Здесь двоеточие отсутствует в операторе def функции.

Кроме того, при трассировке SyntaxError обычная трассировка последней строки отсутствует. Это связано с тем, что ошибка SyntaxError возникает, когда Python пытается проанализировать ваш код, а строки фактически не выполняются.

TypeError

Ошибка TypeError возникает, когда ваш код пытается что-то сделать с объектом, который не может этого сделать, например, пытается добавить строку к целому числу или вызывать len() для объекта, длина которого не определена.

Возникает, когда операция или функция применяется к объекту неподходящего типа. (Источник)

Ниже приведено несколько примеров возникновения TypeError:

>>> 1 + '1'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
>>> '1' + 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: must be str, not int
>>> len(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'int' has no len()

Все вышеприведенные примеры вызова TypeError приводят к строке сообщения об ошибке с разными сообщениями. Каждый из них довольно хорошо информирует о том, что не так.

Первые два примера пытаются добавить строки и целые числа вместе. Тем не менее, они немного отличаются:

  • Первый пытается добавить str к int.
  • Второй пытается добавить int к str.

Строки сообщений об ошибках отражают эти различия.

Последний пример пытается вызвать len() для int. Строка сообщения об ошибке говорит вам, что вы не можете сделать это для int.

ValueError

Ошибка ValueError возникает, когда значение объекта неверно. Вы можете думать об этом как об IndexError, который возникает, потому что значение индекса не находится в диапазоне последовательности, а только ValueError для более общего случая.

Возникает, когда операция или функция получает аргумент, который имеет правильный тип, но недопустимое значение, и ситуация не описывается более точным исключением, таким как IndexError. (Источник)

Вот два примера создания ValueError:

>>> a, b, c = [1, 2]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected 3, got 2)
>>> a, b = [1, 2, 3]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 2)

Строка сообщения об ошибке ValueError в этих примерах говорит вам, в чем именно заключается проблема со значениями:

  1. В первом примере вы пытаетесь распаковать слишком много значений. Строка сообщения об ошибке даже говорит о том, что вы ожидали распаковать 3 значения, но получили 2 значения.
  2. Во втором примере проблема в том, что вы получаете слишком много значений и недостаточно переменных для их распаковки.

Как логировать трассировку?

Получение исключения и полученная в результате трассировка означает, что вам нужно решить, что с этим делать. Обычно исправление кода — это первый шаг, но иногда проблема заключается в неожиданном или неправильном вводе. Несмотря на то, что в вашем коде полезно предусмотреть такие ситуации, иногда имеет смысл замолчать или скрыть исключение, регистрируя трассировку и делая что-то еще.

Вот более реальный пример кода, который должен скрыть некоторые трассировки Python. В этом примере используется библиотека requests. Вы можете узнать больше о ней в Python’s Requests Library (Guide):

# urlcaller.py
import sys
import requests

response = requests.get(sys.argv[1])

print(response.status_code, response.content)

Этот код хорошо работает. Когда вы запустите этот скрипт, задав ему URL-адрес в качестве аргумента командной строки, он вызовет URL-адрес, а затем отобразит код состояния HTTP и содержимое ответа. Это даже работает, если ответ был статус ошибки HTTP:

$ python urlcaller.py https://httpbin.org/status/200
200 b''
$ python urlcaller.py https://httpbin.org/status/500
500 b''

Однако иногда URL-адрес, который выдается для извлечения сценарием, не существует или хост-сервер будет не работать. В этих случаях этот сценарий теперь вызовет необработанное исключение ConnectionError и отобразит трассировку:

$ python urlcaller.py http://thisurlprobablydoesntexist.com
...
During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "urlcaller.py", line 5, in <module>
    response = requests.get(sys.argv[1])
  File "/path/to/requests/api.py", line 75, in get
    return request('get', url, params=params, **kwargs)
  File "/path/to/requests/api.py", line 60, in request
    return session.request(method=method, url=url, **kwargs)
  File "/path/to/requests/sessions.py", line 533, in request
    resp = self.send(prep, **send_kwargs)
  File "/path/to/requests/sessions.py", line 646, in send
    r = adapter.send(request, **kwargs)
  File "/path/to/requests/adapters.py", line 516, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='thisurlprobablydoesntexist.com', port=80): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7faf9d671860>: Failed to establish a new connection: [Errno -2] Name or service not known',))

Трассировка Python здесь может быть очень длинной со многими другими исключениями, которые в конечном итоге приводят к тому, что ConnectionError вызывается самими запросами. Если вы переместитесь вверх по трассировке окончательных исключений, вы увидите, что проблема началась в нашем коде со строки 5 urlcaller.py.

Теперь если вы оберните строку 5 в блок try и except, то перехват соответствующего исключения позволит вашему сценарию продолжить работу:

# urlcaller.py
...
try
    response = requests.get(sys.argv[1])
except requests.exceptions.ConnectionError:
    print(-1, 'Connection Error')
else:
    print(response.status_code, response.content)

Приведенный выше код использует оператор else с блоком try и except. Если вы не знакомы с этой функцией Python, ознакомьтесь с разделом else Python Exceptions: An Introduction.

Теперь, когда вы запустите сценарий с URL-адресом, который приведет к возникновению ошибки ConnectionError, вы получите вывод -1 для кода состояния и строку Connection Error:

$ python urlcaller.py http://thisurlprobablydoesntexist.com
-1 Connection Error

Это прекрасно работает. Однако в большинстве реальных систем вам будет нужно не просто отключать исключение и полученную в результате трассировку, а зарегистрировать трассировку в логах. Регистрация трассировок позволяет вам лучше понять, что не так в ваших программах при анализе логов.

Примечание: Чтобы узнать больше о системе журналирования Python, ознакомьтесь со статьей Логирование в Python (Logging in Python).

Вы можете зарегистрировать трассировку в сценарии, импортировав пакет logging, получив регистратор и вызвав .exception() для этого регистратора в блоке except блока try/except. Ваш финальный скрипт должен выглядеть примерно так:

# urlcaller.py
import logging
import sys
import requests

logger = logging.getLogger(__name__)

try:
    response = requests.get(sys.argv[1])
except requests.exceptions.ConnectionError as e:
    logger.exception()
    print(-1, 'Connection Error')
else:
    print(response.status_code, response.content)

Теперь, когда вы запустите сценарий для проблемного URL, он выведет ожидаемое -1 и Connection Error, но также запишет трассировку в лог:

$ python urlcaller.py http://thisurlprobablydoesntexist.com
...
  File "/path/to/requests/adapters.py", line 516, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='thisurlprobablydoesntexist.com', port=80): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7faf9d671860>: Failed to establish a new connection: [Errno -2] Name or service not known',))
-1 Connection Error

По умолчанию Python отправляет сообщения журнала со стандартной ошибкой в stderr. Так как, мы вообще не подавили вывод трассировки. Однако, если вы вызовете его снова с перенаправленым stderr, вы увидите, что система ведения журнала работает, и мы можем сохранить наши журналы для дальнейшего исследования:

$ python urlcaller.py http://thisurlprobablydoesntexist.com 2> my-logs.log
-1 Connection Error

Заключение

Трассировка содержит важную информацию, которая может помочь вам найти, что идет не так в вашем коде. Эти следы могут выглядеть немного пугающими, но как только вы разберетесь с ними, чтобы увидеть, что они пытаются вам показать, они могут быть очень полезными. Изучение нескольких трассировок построчно даст вам лучшее понимание информации, которую они содержат, и поможет вам извлечь из них максимальную пользу.

Получение вывода трассировки при запуске вашего кода — это отличная возможность улучшить ваш код.

Теперь, когда вы знаете, как читать трассировку, вы можете больше узнать о некоторых инструментах и методах диагностики проблем, о которых рассказывает ваш вывод трассировки. Встроенный модуль traceback может использоваться для работы и проверки трассировок. Модуль трассировки может быть полезен, когда вам нужно получить больше от результатов трассировки. Также было бы полезно узнать больше о некоторых методах отладки кода Python.

Была ли вам полезна эта статья?

[4 / 4.8]

Ошибки и исключения. Обработка исключений

Ошибки и исключения

В любой, особенно большой, программе могут возникать ошибки, приводящие к ее неработоспособности или к тому, что программа делает не то, что должна.
SyntaxError: invalid syntax

В терминологии языка Python здесь возникло исключение, принадлежащее классу SyntaxError. Согласно документации Python синтаксические ошибки все-таки принято относить к ошибкам, а все остальные – к исключениям. В некоторых языках программирования не используется слово «исключение», а ошибки делят на синтаксические и семантические. Нарушение семантики обычно означает, что, хотя выражения написаны верно с точки зрения синтаксиса языка, программа не работает так, как от нее ожидалось. Для сравнения. Вы можете грамотным русским языком сказать несколько предложений, но по смыслу это будет белиберда, или вас поймут не так, как хотелось бы.

В Python не говорят о семантических ошибках, говорят об исключениях. Их множество. В этом уроке мы рассмотрим некоторые из них, в последующих встретимся с еще несколькими.

Если вы попытаетесь обратиться к переменной, которой не было присвоено значение, что в случае Python означает, что переменная вообще не была объявлена, она не существует, то возникнет исключение NameError.

>>> a = 0
>>> print(a + b)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'b' is not defined

Последнюю строку сообщения можно перевести как «Ошибка имени: имя ‘b’ не определено».

Если исключение возникает при выполнении кода из файла, то вместо «line 1» будет указана строка, в которой оно возникло, например, «line 24». Вместо «<stdin>» будет указано имя файла, например, «test.py». В данном же случае stdin обозначает стандартный поток ввода. По-умолчанию это поток ввода с клавиатуры. Строка 1 – потому что в интерактивном режиме каждое выражение интерпретируется отдельно, как обособленная программка. Если написать выражение, состоящее из нескольких строк, то линия возникновения ошибки может быть другой:

>>> a = 0
>>> if a == 0:
...    print(a)
...    print(a + b)
...
0
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
NameError: name 'b' is not defined

Следующие два исключения, о которых следует упомянуть, и с которыми вы уже могли встретиться в предыдущих уроках, это ValueError и TypeError – ошибка значения и ошибка типа.

>>> int("Hi")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() 
with base 10: 'Hi'
>>> 8 + "3"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) 
for +: 'int' and 'str'

В примере строку «Hi» нельзя преобразовать к целому числу. Возникает исключение ValueError, потому что функция int() не может преобразовать такое значение.

Число 8 и строка «3» принадлежат разным типам, операнд сложения между которыми не поддерживается. При попытке их сложить возникает исключение TypeError.

Деление на ноль вызывает исключение ZeroDivisionError:

>>> 1/0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero

Обработка исключений. Оператор try-except

Когда ошибки в программе возникают в процессе написания кода или его тестирования, то код исправляется программистом так, чтобы ошибок не возникало. Однако нередко действия пользователя приводят к тому, что в программе возникает исключение. Например, программа ожидает ввод числа, но человек ввел букву. Попытка преобразовать ее к числу приведет к возбуждению исключения ValueError, и программа аварийно завершится.

На этот случай в языках программирования, в том числе Python, существует специальный оператор, позволяющий перехватывать возникающие исключения и обрабатывать их так, чтобы программа продолжала работать или корректно завершала свою работу.

В Питоне такой перехват выполняет оператор try-except. «Try» переводится как «попытаться», «except» – как исключение. Словами описать его работу можно так: «Попытаться сделать то-то и то-то, если при этом возникло исключение, то сделать вот это и это.» Его конструкция похожа на условный оператор с веткой else. Рассмотрим пример:

n = input("Введите целое число: ")
try:
    n = int(n)
    print("Удачно")
except:
    print("Что-то пошло не так")

Исключительная ситуация может возникнуть в третьей строчке кода, когда значение переменной n преобразуется к целому числу. Если это невозможно, то дальнейшее выполнение выражений в теле try прекращается. В данном случае выражение print("Удачно") выполнено не будет. При этом поток выполнения программы перейдет на ветку except и выполнит ее тело.

Если в теле try исключения не возникает, то тело ветки except не выполняется.

Вот пример вывода программы, когда пользователь вводит целое число:

Введите целое число: 100
Удачно

А здесь – когда вводит не то, что ожидалось:

Введите целое число: AA
Что-то пошло не так

Есть одна проблема. Код выше обработает любое исключение. Однако в теле try могут возникать разные исключения, и у каждого из них должен быть свой обработчик. Поэтому более правильным является указание типа исключения после ключевого слова except.

try:
    n = input('Введите целое число: ')
    n = int(n)
    print("Все нормально. Вы ввели число", n)
except ValueError:
    print("Вы ввели не целое число")

Теперь если сработает тело except мы точно знаем, из-за чего возникла ошибка. Но если в теле try возникнет еще какое-нибудь исключение, то оно не будет обработано. Для него надо написать отдельную ветку except. Рассмотрим программу:

try:
    a = float(input("Введите делимое: "))
    b = float(input("Введите делитель: "))
    c = a / b
    print("Частное: %.2f" % c)
except ValueError:
    print("Нельзя вводить строки")
except ZeroDivisionError:
    print("Нельзя делить на ноль")

При ее выполнении исключения могут возникнуть в трех строчках кода: где происходит преобразование введенных значений к вещественным числам и в месте, где происходит деление. В первом случае может возникнуть ValueError, во втором – ZeroDivisionError. Каждый тип исключения обрабатывается своей веткой except.

Несколько исключений можно сгруппировать в одну ветку и обработать совместно:

try:
    a = float(input("Введите делимое: "))
    b = float(input("Введите делитель: "))
    c = a / b
    print("Частное: %.2f" % c)
except (ValueError, ZeroDivisionError):
    print("Нельзя вводить строки или делить на ноль")

У оператора обработки исключений, кроме except, могут быть еще ветки finally и else (не обязательно обе сразу). Тело finally выполняется всегда, независимо от того, выполнялись ли блоки except в ответ на возникшие исключения или нет. Тело else сработает, если исключений в try не было, т. е. не было переходов на блоки except.

try:
    n = input('Введите целое число: ')
    n = int(n)
except ValueError:
    print("Вы что-то попутали с вводом")
else: # когда в блоке try не возникло исключения
    print("Все нормально. Вы ввели число", n)
finally: # выполняется в любом случае
    print("Конец программы")

Примечание. В данном коде используются комментарии. В языке Python перед ними ставится знак решетки #. Комментарии в программном коде пишутся исключительно для человека и игнорируются интерпретатором или компилятором.

Посмотрите, как выполняется программа в случае возникновения исключения и без этого:

pl@pl-desk:~$ python3 test.py
Введите целое число: 4.3
Вы что-то попутали с вводом
Конец программы
pl@pl-desk:~$ python3 test.py
Введите целое число: 4
Все нормально. Вы ввели число 4
Конец программы

В данном уроке изложены не все особенности обработки исключений. Так в более крупных программах, содержащих несколько уровней вложенности кода, функции, модули и классы, исключения могут обрабатываться не по месту их возникновения, а передаваться дальше по иерархии вызовов.

Также исключение может возникнуть в блоке except, else или finally, и тогда им нужен собственный обработчик. Модифицируем немного предыдущую программу и специально сгенерируем исключение в теле except:

try:
    n = input('Введите целое число: ')
    n = int(n)
except ValueError:
    print("Вы что-то попутали с вводом")
    3 / 0
except ZeroDivisionError:
    print("Деление на ноль")
else:
    print("Все нормально. Вы ввели число", n)
finally:
    print("Конец программы")

По началу может показаться, что все нормально. Исключение, генерируемое выражением 3 / 0 будет обработано веткой except ZeroDivisionError. Однако это не так. Эта ветка обрабатывает только исключения, возникающие в блоке try, к которому она сама относится. Вот вывод программы, если ввести не целое число:

Введите целое число: а
Вы что-то попутали с вводом
Конец программы
Traceback (most recent call last):
File "test.py", line 15, in <module>
n = int(n)

ValueError: invalid literal for 
int() with base 10: 'а'

During handling of the above exception,
another exception occurred:

Traceback (most recent call last):
File "test.py", line 18, in <module>
3 / 0
ZeroDivisionError: division by zero

Мало того, что не было обработано деление на ноль, поскольку тело except ValueError неудачно завершилось, само исключение ValueError посчиталось необработанным. Решение проблемы может быть, например, таким:

…
except ValueError:
    print("Вы что-то попутали с вводом")
    try:
       3 / 0
    except ZeroDivisionError:
        print("Деление на ноль")
…

Здесь в тело except вложен свой внутренний обработчик исключений.

Практическая работа

Напишите программу, которая запрашивает ввод двух значений. Если хотя бы одно из них не является числом, то должна выполняться конкатенация, т. е. соединение, строк. В остальных случаях введенные числа суммируются.

Примеры выполнения программы:

pl@pl-desk:~$ python3 test.py
Первое значение: 4
Второе значение: 5
Результат: 9.0
pl@pl-desk:~$ python3 test.py
Первое значение: a
Второе значение: 9
Результат: a9

Примеры решения и дополнительные уроки в android-приложении и pdf-версии курса

Форматирование Python-кода

Проблемы форматирования

Нет идеального варианта форматирования кода. В каждом языке есть свои особенности и общепринятые нормы, под которые нужно подстраиваться. В python больше всего трудностей в форматировании вызывает «С стиль». Многие приходят в python именно из языков вроде С, соответственно они привыкли писать «)(;». Но не в одних символах проблема, плохи дела еще и с избыточностью написания конструкций. У питона меньше слов, чем у Java, поэтому многим новичкам приходится долго привыкать. На данный момент – это две самые распространенные проблемы.

Стандарты и советы по оформлению

По правильному форматированию кода на python существует даже целый гайд – pep8. Дальше по тексту, будем называть его «стандарт». Почитать о нем на русском вы можете по ссылке http://pep8.ru/doc/pep8/. Он действительно очень обширный, с его помощью программист может сделать действительно читаемый код.

В него входят:
  • Максимальная длинна строчек кода и документации.
  • Рекомендации по правильному оформлению комментариев.
  • Кодировки файлов, содержащих исходный код.
  • Соглашения именования классов/функций, аргументов.
  • И еще много полезного.

По сути он охватывает очень много правил по форматированию кода. Но, пользуются этим стандартом не все, у многих другие предпочтения. У компаний вроде Google есть свои рекомендации, ознакомится с которыми вы можете по ссылкам http://habrahabr.ru/post/179271/ и http://habrahabr.ru/post/180509/.

Автоматизируем форматирование

Почитайте pep8, увидев сколько там правил, вы поймете, что для редактирования нужно ОЧЕНЬ много времени, делать это мало кому за хочется, да и в новом коде все равно будут проскакивать ошибки. Поэтому, есть более простой способ.

Чтобы узнать сколько в коде ошибок оформления понадобиться утилита pep8. Она довольно гибкая, позволяет проверить насколько соответствуют стандарту все файлы в разных папках. Выводит примерно такой результат:

$ pep8 --first optparse.py
optparse.py:69:11: E401 multiple imports on one line
optparse.py:77:1: E302 expected 2 blank lines, found 1
optparse.py:88:5: E301 expected 1 blank line, found 0
optparse.py:222:34: W602 deprecated form of raising exception
optparse.py:347:31: E211 whitespace before '('
optparse.py:357:17: E201 whitespace after '{'
optparse.py:472:29: E221 multiple spaces before operator
optparse.py:544:21: W601 .has_key() is deprecated, use 'in'

Часто одни и те же ошибки дублируются в многих файла. Можно исправить их автоматически – для этого есть утилита autopep8. Она ищет и исправляет ошибки. Пользоваться ей очень просто, вот пример:

$ autopep8 ./ --recursive --in-place -a

Эта команда запускает проверку файлов в папках и их исправление.

Можно воспользоваться еще и autofake. С помощью утилиты мы можем избавится от неиспользуемых переменных и импортов.

Редактирование кода завершается строками. Одни программисты предпочитают писать их в одиночных апострофах, другие в двойных. Это ладно, но под оба варианты есть стандарты и утилита, которая автоматически приведет код к ним – unify.

С кодом разобрались, теперь комментарии. Воспользуемся docformatter. Утилита правильно оформляет их, как документацию.

Все и сразу

Какого-то «комбайна» с этими всеми функциями нет. Но можно его сделать. К примеру, написать bash скрипт, дать ему магическое имя clean.bash и выполнять, когда нужно. Есть и другой вариант – wrapper над утилитами – pyformat.

А если вам нужны запчасти для Японских и других автомобилей – посетите джапан карс. Здесь вы найдете огромный ассортимент автозапчастей. Найти нужную деталь очень легко, можно выполнить поиск по номеру, посмотреть в каталоге или позвонить и вам помогут найти нужное. Если нужной запчасти не найдется, можно ее заказать и получить в кратчайшие сроки.

Python typeerror: объект «список» не вызывается Решение

Когда вы пытаетесь получить доступ к элементам в списке, используя фигурные скобки (()), Python возвращает ошибку. Это потому, что Python думает, что вы пытаетесь вызвать функцию.

В этом руководстве мы говорим об ошибке Python «typeerror:« объект списка »не вызывается» и почему она возникает. Мы рассмотрим пример сценария, который поможет вам узнать, как исправить эту ошибку. Давайте начнем!

Проблема: typeerror: объект ‘list’ не вызывается

Python уже сообщает нам все, что нам нужно знать об этой ошибке:

 typeerror: объект 'list' не вызывается 

Взгляните на тип ошибки : TypeError.Это один из самых распространенных типов ошибок Python. Он сообщает нам, что мы пытаемся манипулировать значением, используя метод, недоступный для того типа данных, в котором это значение хранится.

Наше сообщение об ошибке сообщает нам, что мы пытаемся вызвать объект списка Python. Это означает, что мы рассматриваем его как функцию, а не как список.

Эта ошибка возникает при использовании фигурных скобок для доступа к элементам в списке. Рассмотрим следующий список лепешек:

 scones = [«Вишня», «Яблоко и корица», «Обычный», «Сыр»] 

Чтобы получить доступ к элементам в этом списке, мы должны указать порядковый номер значения, которое мы хотите получить доступ в квадратных скобках:

Это возвращает: Cherry.0 — это позиция первого элемента в нашем списке «Вишня».

Пример сценария

Мы собираемся создать программу на Python, которая использует список имен с большой буквы. Мы должны использовать первые буквы этих имен с большой буквы, потому что они будут напечатаны на визитках.

Начните с объявления списка имен:

 names = ["Питер Джеффри", "Дакота Уильямс", "Ребекка Ли"] 

Затем создайте цикл for, который повторяет этот список имен. Мы преобразуем каждое имя в верхний регистр и заменим имя в нижнем регистре на имя в верхнем регистре в списке:

 для n в диапазоне (len (names)):
имена [n] = имена (n).верхний ()
печать (имена (n))

print (names) 

Используйте метод range () для итерации по каждому элементу в списке «names». Затем используйте оператор присваивания, чтобы изменить значение каждого имени на его эквивалент в верхнем регистре. Метод Python upper () преобразует каждое имя в верхний регистр.

Затем распечатайте новое имя на консоли. Как только наш цикл будет выполнен, распечатайте весь измененный список на консоли.

Давайте запустим наш код:

 Traceback (последний вызов последний):
  Файл "main.py ", строка 4, в 
имена [n] = имена (n) .upper ()
TypeError: объект 'list' не вызывается 

Мы получили ошибку, как и ожидалось. Давайте решим эту проблему.

Решение

Используйте квадратные скобки для доступа к элементам в списке. Фигурные скобки используются для вызова функций в Python. Проблема в нашем коде заключается в том, что мы пытаемся вызвать список как функцию, потому что для доступа к элементам в нашем списке мы используем фигурные скобки.

В нашем коде используйте фигурные скобки для доступа к элементу списка в двух местах:

 для n в диапазоне (len (имена)):
имена [n] = имена (n).верхний ()
print (names (n)) 

Мы должны поменять местами код names (n), чтобы использовать квадратные скобки:

 для n в диапазоне (len (names)):
имена [n] = имена [n] .upper ()
print (names [n]) 

Это говорит Python, что мы хотим получить доступ к элементу в позиции индекса «n» в списке «names».

Запустите наш код с применимыми ревизиями, которые мы только что обсудили:

 ПИТЕР ДЖОФФРИ
ДАКОТА УИЛЬЯМС
РЕБЕККА ЛИ

['ПИТЕР ДЖОФФРИ', 'ДАКОТА УИЛЬЯМС', 'РЕБЕККА ЛИ'] 

На этот раз возвращается успешный ответ.Каждое имя переводится в заглавные буквы.

Версия имени, написанная заглавными буквами, заменяет версию имени в регистре предложений. Затем мы выводим каждое имя на консоль. Когда наша программа завершена, мы распечатываем список всех имен в «names», чтобы проверить, что они были изменены в нашем списке.

Заключение

Ошибка Python «typeerror: объект« список »не вызывается» возникает, когда вы пытаетесь получить доступ к списку, как если бы это была функция. Чтобы решить эту ошибку, убедитесь, что для доступа к значениям в списке или их изменения используются квадратные скобки, а не фигурные скобки.

Теперь вы готовы исправить эту ошибку в своем коде, как профессиональный разработчик Python!

Встроенные исключения — документация Python 3.9.0

В Python все исключения должны быть экземплярами класса, производного от
BaseException . В операторе попробуйте с , кроме
предложение, в котором упоминается конкретный класс, это предложение также обрабатывает любое исключение
классы, производные от этого класса (но не классы исключений, из которых это
производное).Два класса исключений, которые не связаны через подклассы, никогда не
эквивалент, даже если у них одно и то же имя.

Встроенные исключения, перечисленные ниже, могут быть сгенерированы интерпретатором или
встроенные функции. Если не указано иное, у них есть «связанное значение».
с указанием подробной причины ошибки. Это может быть строка или кортеж
несколько элементов информации (например, код ошибки и строка, объясняющая
код). Связанное значение обычно передается в качестве аргументов исключению.
конструктор класса.

Код пользователя может вызывать встроенные исключения. Это можно использовать для проверки исключения
обработчик или сообщить об ошибке «точно так же, как» ситуация, в которой
интерпретатор вызывает то же исключение; но будьте осторожны, нечего
предотвратить появление несоответствующей ошибки пользовательским кодом.

Встроенные классы исключений могут быть разделены на подклассы для определения новых исключений;
программистам рекомендуется выводить новые исключения из Exception
class или один из его подклассов, а не из BaseException .Больше
информация об определении исключений доступна в Руководстве по Python в разделе
Пользовательские исключения.

При повышении (или повторном повышении) исключения в , кроме или
наконец пункт
__context__ автоматически устанавливается на последнее обнаруженное исключение; если
новое исключение не обрабатывается, трассировка, которая в конечном итоге отображается, будет
включить исходное исключение (я) и последнее исключение.

При создании нового исключения (вместо использования простого повышения для повторного повышения
исключение, которое в настоящее время обрабатывается), неявный контекст исключения может быть
дополнен явной причиной с использованием из с
поднять :

 поднять new_exc из original_exc
 

Выражение, следующее за из , должно быть исключением или Нет .Это
будет установлено как __cause__ для возникшего исключения. Настройка
__cause__ также неявно устанавливает __suppress_context__
атрибут True , так что использование поднимает new_exc с None
эффективно заменяет старое исключение новым для отображения
целей (например, преобразование KeyError в AttributeError ), а
оставляя старое исключение доступным в __context__ для самоанализа
при отладке.

Код отображения трассировки по умолчанию показывает эти связанные исключения в
дополнение к трассировке самого исключения.Явно связанный
исключение в __cause__ всегда отображается, если присутствует. Неявно
связанное исключение в __context__ отображается, только если __cause__
равно Нет и __suppress_context__ ложно.

В любом случае само исключение всегда отображается после любого связанного
исключения, чтобы в последней строке трассировки всегда отображалась последняя
возникшее исключение.

Базовые классы

Следующие исключения используются в основном как базовые классы для других исключений.

исключение BaseException

Базовый класс для всех встроенных исключений. Это не должно быть напрямую
inher

Общие сообщения об ошибках Python 3 (и способы их устранения!)

Общие сообщения об ошибках Python 3 (и способы их устранения!)

Общие сообщения об ошибках Python 3 (и способы их устранения!)

Последняя редакция: август 2010 г.

(Макканн)

Целевая аудитория этого документа — осенний курс ISTA 130 2010 г.
Университет Аризоны.Если другие люди тоже сочтут это полезным — отлично!


Список сообщений об ошибках

Нажмите на название сообщения, чтобы узнать, что могло вызвать
это и несколько предложений о том, как решить проблему.

  1. SyntaxError: недопустимый синтаксис
  2. IndentationError: ожидается блок с отступом
  3. IndentationError: неожиданный отступ
  4. NameError: глобальное имя ‘—‘ не определено
  5. TypeError: невозможно неявно преобразовать объект int в str

  1. SyntaxError: недопустимый синтаксис

    Синтаксис языка — это набор правил, определяющих, что
    части языка могут появляться в каких местах.Если вы вставите
    вкладка A в слот B, так сказать, вы создадите оператор, который
    имеет неверный синтаксис. Потому что в Python много слотов, которые
    не принимайте большинство вкладок, генерировать синтаксическую ошибку несложно.

    Вот несколько распространенных ошибок, вызывающих это сообщение:

    • Забыть скобки вокруг аргументов для печати
    • Забыть двоеточие в конце условия в
      если заявление
    • Попытка использовать зарезервированное слово в качестве имени переменной
  2. IndentationError: ожидается блок с отступом

    Отступы программных операторов имеют решающее значение для удобочитаемости
    кода.Большинство языков программирования допускают отступы, но не
    обеспечить его соблюдение. Питон добивается этого железным кулаком. Всякий раз, когда вам
    есть ситуация с кодом внутри оператора (например,
    код, определяющий функцию main ()), этот внутренний код
    должны быть с отступом и должны иметь последовательный отступ. Если ты забудешь
    чтобы сделать отступ, вы увидите эту ошибку.

    Вот некоторые распространенные причины этой ошибки:

    • Забывание отступов в операторах в составе
      заявление (например, тела if и for)
    • Забыть сделать отступ в операторах пользовательской функции
  3. IndentationError: неожиданный отступ

    Как упоминалось в разделе «Ожидается блок с отступом», Python
    не только настаивает на отступе, он настаивает на последовательном отступе.Вы можете выбрать количество используемых отступов,
    но тогда вам нужно придерживаться этого. Если вы сделаете отступ в одну строку на 4
    пробелы, но затем сделайте отступ следующего на 3 (или 5, или 19, или …),
    вы получите эту ошибку.

    Вот некоторые распространенные причины этой ошибки:

    • Забывание отступов в операторах в составе
      заявление (например, тела if и for)
    • Забыть сделать отступ в операторах пользовательской функции
  4. NameError: глобальное имя ‘—‘ не определено

    Python знает назначение определенных имен (например, имен
    встроенные функции вроде печати).Другие имена определены
    внутри программы (например, переменные). Если Python встречает
    имя, которое он не распознает, вы, вероятно, получите эту ошибку.

    Вот некоторые распространенные причины этой ошибки:

    • Забыл присвоить переменной значение перед ее использованием в
      другое заявление
    • Ошибочное написание имени встроенной функции (например, ввод
      «inpit» вместо «input»)
  5. TypeError: не удается неявно преобразовать объект int в str

    Переменные Python «знают» типы значений, которые они хранят, что позволяет
    Python, чтобы сообщить вам, когда вы пытаетесь сделать что-то странное, например
    as используйте оператор сложения, чтобы объединить число и строку
    (answer = «Привет» + 1).

    Распространенная причина этой ошибки — забыть использовать eval ()
    с input () при запросе пользователя ввести числовое значение
    с клавиатуры.


У вас есть комментарий к этой странице? Я бы хотел это услышать; вы можете написать мне на
[email protected].

Документация

Learning with Python 2nd Edition

В программе могут возникать различные типы ошибок, и это полезно
различать их, чтобы быстрее выследить:

  1. Синтаксические ошибки создаются Python при переводе исходного кода
    в байтовый код.Обычно они указывают на то, что что-то не так с
    синтаксис программы. Пример: опускание двоеточия в конце def
    оператор дает несколько избыточное сообщение SyntaxError: invalid
    синтаксис.
  2. Ошибки времени выполнения создаются системой времени выполнения, если что-то пойдет не так
    пока программа работает. Большинство сообщений об ошибках времени выполнения включают
    информация о том, где произошла ошибка и какие функции были
    выполнение. Пример: бесконечная рекурсия в конечном итоге вызывает ошибку времени выполнения
    максимальной глубины рекурсии превышена.
  3. Семантические ошибки — это проблемы с программой, которая компилируется и запускается, но
    поступает неправильно. Пример: выражение не может быть вычислено в
    ожидаемый порядок, дающий неожиданный результат.

Первый шаг в отладке — выяснить, какая у вас ошибка
имея дело с. Хотя следующие разделы организованы по типам ошибок, некоторые
методы применимы более чем в одной ситуации.

Синтаксические ошибки

Синтаксические ошибки обычно легко исправить, если вы выясните, в чем они заключаются.К сожалению, сообщения об ошибках часто бесполезны. Самый распространенный
сообщения являются SyntaxError: недопустимый синтаксис и SyntaxError: invalid
токен, ни то, ни другое не очень информативно.

С другой стороны, сообщение говорит вам, где в программе проблема.
произошло. Фактически, он сообщает вам, где Python заметил проблему, а это не
обязательно где ошибка. Иногда ошибка предшествует местонахождению
сообщение об ошибке, часто в предыдущей строке.

Если вы строите программу постепенно, у вас должна быть хорошая идея
о том, где ошибка.Он будет в последней добавленной вами строке.

Если вы копируете код из книги, начните со сравнения своего кода с кодом книги.
кодируйте очень внимательно. Проверьте каждого персонажа. В то же время помните, что
книга может быть неправильной, поэтому, если вы видите что-то похожее на синтаксическую ошибку, она
возможно.

Вот несколько способов избежать наиболее распространенных синтаксических ошибок:

  1. Убедитесь, что вы не используете ключевое слово Python для имени переменной.
  2. Убедитесь, что у вас есть двоеточие в конце заголовка каждого соединения
    оператор, включая операторы for, while, if и def.
  3. Убедитесь, что отступы совпадают. Вы можете сделать отступ либо пробелами, либо
    вкладки, но лучше не смешивать их. Каждый уровень должен быть одинаковым
    количество.
  4. Убедитесь, что все строки в коде имеют соответствующие кавычки.
  5. Если у вас есть многострочные строки с тройными кавычками (одинарными или двойными), сделайте
    убедитесь, что вы правильно завершили строку. Незавершенная строка может
    вызвать ошибку неверного токена в конце вашей программы, или это может лечить
    следующая часть программы в виде строки, пока не дойдет до следующего
    строка.Во втором случае он может вообще не выдавать сообщения об ошибке!
  6. Незакрытая скобка — (, {или [- заставляет Python продолжить
    строка как часть текущего оператора. Как правило, ошибка возникает почти
    сразу в следующей строке.
  7. Проверьте классический = вместо == внутри условного выражения.

Если ничего не работает, переходите к следующему разделу …

Я не могу запустить свою программу, что бы я ни делал.

Если компилятор сообщает об ошибке, а вы ее не видите, это может быть
потому что вы и компилятор не смотрите на один и тот же код.Проверьте свои
среды программирования, чтобы убедиться, что редактируемая программа
один Python пытается запустить. Если вы не уверены, попробуйте поставить очевидное и
умышленная синтаксическая ошибка в начале программы. Теперь запустите (или импортируйте) его
еще раз. Если компилятор не находит новую ошибку, вероятно, что-то
неправильно настроен в вашей среде.

Если это произойдет, один из способов — начать заново с новой программы, например Hello,
World !, и убедитесь, что вы можете запустить известную программу.Затем постепенно добавляйте
кусочки новой программы к рабочей.

Ошибки выполнения

Если ваша программа синтаксически верна, Python может импортировать ее и, по крайней мере,
запустить его. Что возможно могло пойти не так?

Моя программа абсолютно ничего не делает.

Эта проблема чаще всего возникает, когда ваш файл состоит из функций и классов.
но на самом деле ничего не вызывает для запуска выполнения. Это может быть
преднамеренно, если вы планируете импортировать этот модуль только для предоставления классов и
функции.

Если это не намеренно, убедитесь, что вы вызываете функцию для запуска
выполнение или выполните одно из интерактивных подсказок. Также см. Поток
Раздел исполнения ниже.

Моя программа зависает.

Если программа останавливается и кажется, что она ничего не делает, мы говорим, что она зависла. Часто
это означает, что он попал в бесконечный цикл или бесконечную рекурсию.

  1. Если есть определенная петля, которая, как вы подозреваете, является проблемой, добавьте
    оператор печати непосредственно перед циклом, который говорит о входе в цикл
    а другой сразу после этого говорит о выходе из цикла.
  2. Запустите программу. Если вы получили первое сообщение, а не второе, значит, вы получили
    бесконечный цикл. Перейдите в раздел «Бесконечный цикл» ниже.
  3. В большинстве случаев бесконечная рекурсия заставляет программу работать в течение
    в то время как, а затем произвести RuntimeError: максимальная глубина рекурсии превышена
    ошибка. Если это произойдет, перейдите к бесконечной рекурсии.
    раздел ниже.
  4. Если вы не получаете эту ошибку, но подозреваете, что проблема связана с
    рекурсивный метод или функцию, вы все равно можете использовать методы в
    Раздел бесконечной рекурсии.
  5. Если ни один из этих шагов не сработает, начните тестирование других петель и других
    рекурсивные функции и методы.
  6. Если это не сработает, возможно, вы не понимаете процесс
    исполнения в вашей программе. Перейдите к разделу «Ход выполнения» ниже.

Бесконечный цикл

Если вы думаете, что у вас бесконечный цикл, и вы думаете, что знаете, что такое цикл
вызывая проблему, добавьте оператор печати в конце цикла, который
печатает значения переменных в условии и значение
состояние.

Например:

, а x> 0 и y <0:
    # сделать что-нибудь с x
    # сделать что-нибудь с y

    напечатайте "x:", x
    напечатайте "y:", y
    напечатать «условие:», (x> 0 и y <0)
 

Теперь, когда вы запустите программу, вы увидите три строки вывода для каждого раза
через петлю. При последнем прохождении цикла условие должно быть
ложный. Если цикл продолжится, вы сможете увидеть значения x
и y, и вы можете понять, почему они не обновляются правильно.

Бесконечная рекурсия

В большинстве случаев бесконечная рекурсия заставляет программу работать в течение
while, а затем выдает ошибку Превышена максимальная глубина рекурсии.

Если вы подозреваете, что функция или метод вызывает бесконечную рекурсию,
начните с проверки, чтобы убедиться, что существует базовый вариант. Другими словами,
должно быть какое-то условие, которое приведет к возврату функции или метода
без рекурсивного вызова. Если нет, то нужно переосмыслить
алгоритм и определить базовый случай.

Если есть базовый вариант, но программа не достигает его, добавьте
оператор печати в начале функции или метода, который печатает
параметры. Теперь, когда вы запустите программу, вы увидите несколько строк вывода
каждый раз, когда вызывается функция или метод, и вы увидите параметры.
Если параметры не приближаются к базовому варианту, вы получите некоторые идеи
о том, почему бы и нет.

Порядок исполнения

Если вы не уверены, как поток выполнения движется по вашей программе,
добавьте операторы печати в начало каждой функции с сообщением типа
ввод функции foo, где foo - это имя функции.

Теперь, когда вы запустите программу, она распечатает трассировку каждой функции, как есть.
вызван.

Когда я запускаю программу, я получаю исключение.

Если что-то пойдет не так во время выполнения, Python распечатает сообщение, содержащее
название исключения, строка программы, в которой возникла проблема,
и обратная связь.

Отслеживание идентифицирует функцию, которая в настоящее время выполняется, а затем
функция, которая его вызвала, а затем функция, которая вызвала , и так далее.Другими словами, он отслеживает путь вызовов функций, которые привели вас к
где ты. Он также включает номер строки в вашем файле, где каждый из
эти звонки происходят.

Первый шаг - проверить место в программе, где произошла ошибка.
и посмотрите, сможете ли вы выяснить, что произошло. Это одни из самых распространенных
ошибок выполнения:

NameError
Вы пытаетесь использовать переменную, которой нет в текущем
Окружающая среда. Помните, что локальные переменные локальны.Вы не можете ссылаться на
их извне функции, в которой они определены.
Тип Ошибка

Есть несколько возможных причин:

  1. Вы пытаетесь использовать значение неправильно. Пример: индексация
    строка, список или кортеж с чем-либо, кроме целого числа.
  2. Несоответствие между элементами в строке формата и
    предметы, переданные на конвертацию. Это может произойти, если количество
    элементы не совпадают или требуется недопустимое преобразование.
  3. Вы передаете неправильное количество аргументов функции или
    метод. Что касается методов, посмотрите определение метода и убедитесь, что
    первый параметр - self. Затем посмотрите на вызов метода; сделать
    убедитесь, что вы вызываете метод для объекта с правильным типом и
    правильное предоставление других аргументов.
KeyError
Вы пытаетесь получить доступ к элементу словаря, используя значение ключа,
словарь не содержит.
AttributeError
Вы пытаетесь получить доступ к несуществующему атрибуту или методу.
IndexError
Индекс, который вы используете для доступа к списку, строке или кортежу, больше, чем
его длина минус один. Непосредственно перед местом ошибки добавьте
оператор печати для отображения значения индекса и длины
массив. Правильный ли размер массива? Является ли индекс правильным значением?

Я добавил так много операторов печати, что меня завалили выводами.

Одна из проблем с использованием операторов печати для отладки:
что вы можете оказаться похороненным на выходе.Есть два способа продолжить:
упростить вывод или упростить программу.

Для упрощения вывода вы можете удалить или закомментировать печать
утверждения, которые не помогают, или объединяют их, или форматируют вывод
так легче понять.

Чтобы упростить программу, вы можете сделать несколько вещей. Первый,
уменьшить проблему, над которой работает программа. Например, если вы
сортируют массив, отсортируйте небольшой массив . Если программа принимает ввод
от пользователя введите простейший ввод, вызывающий проблему.

Во-вторых, очистите программу. Удалите мертвый код и реорганизуйте
программа, чтобы сделать ее максимально удобной для чтения. Например, если вы
подозреваете, что проблема в глубоко вложенной части программы,
попробуйте переписать эту часть с более простой структурой. Если вы подозреваете большой
функция, попробуйте разделить ее на более мелкие функции и протестировать их
по отдельности.

Часто процесс поиска минимального тестового примера приводит вас к
ошибка. Если вы обнаружите, что программа работает в одной ситуации, но не в
другой, который дает вам представление о том, что происходит.

Точно так же переписывание фрагмента кода может помочь вам найти незаметные ошибки. Если
вы вносите изменения, которые, по вашему мнению, не повлияют на программу, и
делает, это может вас подсказать.

Семантические ошибки

В некотором смысле семантические ошибки труднее всего отлаживать, поскольку
компилятор и исполняющая система не предоставляют информации о том, что
неправильно. Только вы знаете, что программа должна делать, и только вы
знайте, что он этого не делает.

Первый шаг - установить связь между текстом программы и
поведение, которое вы видите.Вам нужна гипотеза о том, что
программа на самом деле делает. Одна из причин, по которой это сложно, - это
что компьютеры работают так быстро.

Вы часто будете хотеть, чтобы вы могли замедлить программу до человеческого
скорость, и с некоторыми отладчиками вы можете. Но время, необходимое для
вставить несколько хорошо размещенных операторов печати часто бывает короче по сравнению с
настройка отладчика, вставка и удаление точек останова и
переход программы к месту возникновения ошибки.

Моя программа не работает.

Задайте себе следующие вопросы:

  1. Есть ли что-то, что программа должна была делать, но чего не сделала?
    кажется, происходит? Найдите раздел кода, который выполняет это
    функция и убедитесь, что она выполняется, когда вы считаете нужным.
  2. Что-то происходит, чего не должно быть? Найдите код в своей программе
    который выполняет эту функцию, и посмотрите, выполняется ли она, когда она
    не должен.
  3. Это часть кода, производящая эффект, который вы не
    ожидается? Убедитесь, что вы понимаете рассматриваемый код,
    особенно если это связано с вызовами функций или методов в других
    Модули Python.Прочтите документацию по вызываемым функциям.
    Попробуйте их, написав простые тестовые примеры и проверив результаты.

Чтобы программировать, вам нужна ментальная модель того, как
Работа. Если вы напишете программу, которая не сделает то, что вы ожидаете, очень
часто проблема не в программе; это в вашей ментальной модели.

Лучший способ исправить вашу ментальную модель - разбить программу на
его компоненты (обычно функции и методы) и тестируйте каждый
компонент самостоятельно.Как только вы обнаружите несоответствие между вашими
модель и реальность, можно решить проблему.

Конечно, вы должны создавать и тестировать компоненты по мере того, как
разработать программу. Если вы столкнулись с проблемой, должно быть только
небольшой объем нового кода, который, как известно, неверен.

У меня большое волосатое выражение лица, и оно не соответствует моим ожиданиям.

Написание сложных выражений - это хорошо, если они читабельны, но
их может быть трудно отладить. Часто бывает хорошей идеей сломать сложный
выражение в серию присвоений временным переменным.

Например:

 self.hands [i] .addCard (self.hands [self.findNeighbor (i)]. PopCard ())
 

Это можно переписать как:

 сосед = self.findNeighbor (i)
PickCard = self.hands [сосед] .popCard ()
self.hands [i] .addCard (выбранная карта)
 

Явная версия легче читать, потому что имена переменных обеспечивают
дополнительная документация, и ее легче отлаживать, потому что вы можете проверить
типы промежуточных переменных и отображают их значения.

Другая проблема, которая может возникнуть с большими выражениями, заключается в том, что порядок
оценка может быть не такой, как вы ожидаете. Например, если вы переводите
выражение x / 2pi в Python можно написать:

Это неверно, потому что умножение и деление имеют одно и то же
приоритет и оцениваются слева направо. Итак, это выражение вычисляет
(х / 2) пи.

Хороший способ отладки выражений - добавить круглые скобки, чтобы упорядочить
оценка явная:

Если вы не уверены в порядке оценки, используйте круглые скобки.Не
только программа будет правильной (в том смысле, что она будет делать то, что задумано),
также будет более читаемым для других людей, которые не запомнили правила
приоритет.

У меня есть функция или метод, которые не возвращают то, что я ожидал.

Если у вас есть оператор return со сложным выражением, у вас нет
возможность распечатать возвращаемое значение перед возвратом. Опять же, вы можете использовать
временная переменная. Например, вместо:

 return self.hands [i] .removeMatches ()
 

можно написать:

 count = self.hands [i] .removeMatches ()
счетчик возврата
 

Теперь у вас есть возможность отображать значение счета перед
возвращение.

Я действительно застрял, и мне нужна помощь.

Сначала попробуйте отойти от компьютера на несколько минут. Компьютеры излучают
волны, которые влияют на мозг, вызывая эти эффекты:

  1. Разочарование и / или ярость.
  2. Суеверные убеждения (компьютер меня ненавидит) и магическое мышление (
    программа работает только когда я ношу шляпу задом наперед).
  3. Программирование случайным блужданием (попытка программировать, записывая все возможные
    программу и выбрав ту, которая правильно работает).

Если вы обнаружите, что страдаете от любого из этих симптомов, встаньте и сделайте
ходить. Когда вы будете спокойны, подумайте о программе. Что он делает? Что
какие-то возможные причины такого поведения? Когда вы в последний раз работали
программа, а что вы делали дальше?

Иногда требуется время, чтобы найти ошибку. Мы часто находим ошибки, когда мы в отъезде
от компьютера и позвольте нашему разуму блуждать.Некоторые из лучших мест для поиска
жуки бывают поездами, душами и в постели, прямо перед тем, как уснуть.

Нет, мне действительно нужна помощь.

Бывает. Даже лучшие программисты иногда застревают. Иногда вы
работать над программой так долго, что вы не можете увидеть ошибку. Свежая пара глаз
это просто вещь.

Прежде чем приводить кого-то еще, убедитесь, что вы исчерпали все техники
описано здесь. Ваша программа должна быть максимально простой, и вы должны
работает с наименьшим входом, вызывающим ошибку.У вас должна быть печать
операторы в соответствующих местах (и вывод, который они производят, должен быть
приемлемо). Вы должны достаточно хорошо понять проблему, чтобы описать ее
лаконично.

Когда вы приглашаете кого-нибудь на помощь, не забудьте сообщить ему информацию, которую он
нужно:

  1. Если появляется сообщение об ошибке, что это такое и какая часть программы выполняет
    это указать?
  2. Что вы делали в последний раз перед возникновением этой ошибки? Какие были
    последние строки кода, который вы написали, или какой новый тестовый пример не прошел?
  3. Что вы пробовали до сих пор и чему научились?

Когда вы найдете ошибку, подумайте, что вы могли бы сделать с ней.
найди быстрее.В следующий раз, когда вы увидите что-то подобное, вы сможете найти
ошибка быстрее.

Помните, цель - не просто заставить программу работать. Цель - научиться
как заставить программу работать.

Линтеры и средства форматирования - документация по Essential Python Tools 3.7

PEP8

PEP8 - официальное руководство по стилю для Python. Если вы хотите стать частью сообщества Python, важно знать руководство по стилю.

Правила кодирования PEP8:
  • Пробелы - предпочтительный метод отступа.
  • Используйте 4 пробела на каждый уровень отступа.
  • Ограничьте все строки до 79 символов.
  • Разделите определения функций и классов на верхнем уровне двумя пустыми строками.
  • Определения методов внутри класса заключаются в одну пустую строку.
  • Импорт следует сгруппировать в следующем порядке:
    • Импорт стандартных библиотек.
    • Связанный импорт третьих сторон.
    • Импорт, специфичный для локального приложения / библиотеки.
    • Пустая строка между каждой группой импорта.

пикодестиль

Pycodestyle (ранее PEP8) - это официальный инструмент линтера для проверки кода python на соответствие стилевым соглашениям PEP8 python.

Для его установки:
pip install pycodestyle .

Давайте возьмем небольшой пример скрипта для тестирования pycodestyle

Мы создадим файл тестового скрипта test_script.py и будем использовать его в качестве примера для всех линтеров.

 из __future__ import print_function
import os, sys
импорт журнала
из .. импорт просмотров

класс DoSomething (SomeCommand):

    def __init __ (сам):
        для i в диапазоне (1,11):
            если self.number == i:
                print ("совпадает")
            еще:
                print ('не соответствует')

    def check_user (сам):
        если self.user: вернуть True
        else: вернуть False
 

Если запустить pycodestyle:
$ pycodestyle {source_file_or_directory}

 $ pycodestyle test_script.ру
test_script.py:2:10: E401 множественный импорт в одной строке
test_script.py:6:1: E302 ожидал 2 пустых строки, найдено 1
test_script.py:6:31: E203 пробел перед ':'
test_script.py:9:25: E231 отсутствует пробел после ','
test_script.py:13:37: W291 завершающий пробел
test_script.py:16:21: E701 несколько операторов в одной строке (двоеточие)
test_script.py:16:34: W291 завершающий пробел
test_script.py:17:13: E271 несколько пробелов после ключевого слова
test_script.py:17:14: E203 пробел перед ':'
test_script.py:17:15: E701 несколько операторов в одной строке (двоеточие)
test_script.py: 17: 29: W291 конечный пробел
 

Чтобы увидеть сводку, используйте --statistics -qq
$ pycodestyle --statistics -qq {исходный_файл_или_каталог}

 $ pycodestyle --statistics -qq test_script.py
    2 E203 пробел перед ':'
    1 E231 отсутствует пробел после ','
    1 E271 несколько пробелов после ключевого слова
    1 E302 ожидается 2 пустые строки, найдено 1
    1 E401 множественный импорт на одной строке
    2 E701 несколько операторов в одной строке (двоеточие)
    3 W291 конечный пробел
 

Мы также можем заставить pycodestyle отображать ошибку и описание того, как исправить ошибку, используя --show-source --show-pep8

$ pycodestyle --show-source --show-pep8 {source_file_or_directory}

 $ pycodestyle --show-source --show-pep8 test_script.Поместите импорт в отдельные строки.
    ...
    ...
    ...
 

Чтобы настроить pycodestyle , мы можем настроить его на уровне проекта или на уровне пользователя.
Лучше настраивать на уровне проекта, поскольку стиль обычно меняется для каждого проекта.

Чтобы настроить на , в пикодестиле проекта создайте tox.ini или setup.cfg

И прибавляем

 [пикодестиль]
игнорировать = E501, W291
максимальная длина строки = 88
статистика = Истина
 
В указанном выше файле
  • [pycodestyle] сообщает, что это секция pycodestyle
  • , мы говорим игнорировать ошибку E501 (ошибка длины строки) и предупреждение W291 (предупреждение о конечных пробелах).
  • с указанием максимальной длины строки 88.
  • и показывать статистику при каждой проверке
Код ошибки / предупреждения PEP8
Ошибка / предупреждение Значение
Начиная с E… Ошибки
Начиная с W… Предупреждения
100 тип… Отступ
200 тип… Пробел
300 тип… Пустые строки
400 тип… Импорт
500 тип… Длина линии
600 тип… Прекращение поддержки
700 тип… Заявления
900 тип… Синтаксические ошибки

пилынт

Pylint - это Python-линтер, который проверяет исходный код, а также действует как средство проверки ошибок и качества.У него больше проверок и опций, чем просто PEP8 (руководство по стилю Python).

Это наиболее часто используемый инструмент для линтинга в Python.

Включает в себя следующие функции:
  • Проверка длины каждой строки
  • Проверка правильности формирования имен переменных в соответствии со стандартом кодирования проекта
  • Проверка правильности реализации заявленных интерфейсов.

Для его установки:
pip install pylint .(плохие пробелы)
C: 1, 0: Отсутствует строка документации модуля (missing-docstring)
C

Ошибки Python и встроенные исключения

Мы можем делать определенные ошибки при написании программы, которые приводят к ошибкам при попытке ее запустить. Программа python завершает работу, как только обнаруживает необработанную ошибку. Эти ошибки можно условно разделить на два класса:

  1. Синтаксические ошибки
  2. Логические ошибки (исключения)

Синтаксические ошибки Python

Ошибка, вызванная несоблюдением правильной структуры (синтаксиса) языка, называется синтаксической ошибкой или ошибкой синтаксического анализа .SyntaxError: недопустимый синтаксис

Как показано в примере, стрелка указывает, где синтаксический анализатор обнаружил синтаксическую ошибку.

Здесь можно заметить, что двоеточие : отсутствует в операторе if .


Логические ошибки Python (исключения)

Ошибки, возникающие во время выполнения (после прохождения синтаксической проверки), называются исключениями или логическими ошибками .

Например, они возникают, когда мы пытаемся открыть файл (для чтения), который не существует ( FileNotFoundError ), пытаемся разделить число на ноль ( ZeroDivisionError ) или пытаемся импортировать несуществующий модуль ( ImportError ).

Каждый раз, когда возникают эти типы ошибок времени выполнения, Python создает объект исключения. Если не обработать должным образом, он распечатывает трассировку этой ошибки вместе с некоторыми подробностями о том, почему эта ошибка произошла.

Давайте посмотрим, как Python обрабатывает эти ошибки:

  >>> 1/0
Отслеживание (последний вызов последний):
 Файл «<строка>», строка 301, в коде выполнения
 Файл «<интерактивный ввод>», строка 1, в <модуле>
ZeroDivisionError: деление на ноль

>>> open ("мнимый.текст")
Отслеживание (последний вызов последний):
 Файл «<строка>», строка 301, в коде выполнения
 Файл «<интерактивный ввод>», строка 1, в <модуле>
FileNotFoundError: [Errno 2] Нет такого файла или каталога: 'imaginary.txt'  

Встроенные исключения Python

Незаконные операции могут вызывать исключения. В Python есть множество встроенных исключений, которые возникают при возникновении соответствующих ошибок. Мы можем просмотреть все встроенные исключения, используя встроенную функцию local () следующим образом:

  print (dir (locals () ['__ builtins__']))  

locals () ['__ builtins__'] вернет модуль встроенных исключений, функций и атрибутов. dir позволяет нам перечислить эти атрибуты в виде строк.

Некоторые из распространенных встроенных исключений в программировании на Python, а также ошибки, вызывающие их, перечислены ниже:

Исключение Причина ошибки
AssertionError Возникает при сбое утверждения утверждения .
Ошибка атрибута Возникает при сбое присвоения атрибута или ссылки.
EOFError Возникает, когда функция input () достигает условия конца файла.
Ошибка плавающей точки Возникает при сбое операции с плавающей запятой.
Выход генератора Возникает при вызове метода close () генератора.
ImportError Возникает, когда импортированный модуль не найден.
Ошибка индекса Возникает, когда индекс последовательности выходит за пределы допустимого диапазона.
KeyError Возникает, когда ключ не найден в словаре.
Прерывание клавиатуры Возникает, когда пользователь нажимает клавишу прерывания ( Ctrl + C или Delete ).
Ошибка памяти Возникает, когда для операции не хватает памяти.
NameError Возникает, когда переменная не найдена в локальной или глобальной области.
NotImplementedError Поднят абстрактными методами.
Ошибка OS Возникает, когда работа системы вызывает системную ошибку.
Ошибка переполнения Возникает, когда результат арифметической операции слишком велик для представления.
Ссылка Ошибка Возникает, когда слабый ссылочный прокси используется для доступа к референту со сборкой мусора.
RuntimeError Возникает, когда ошибка не попадает ни в одну другую категорию.
StopIteration Вызывается функцией next () , чтобы указать, что итератор больше не может вернуть элемент.
SyntaxError Возникает синтаксическим анализатором при обнаружении синтаксической ошибки.
Ошибка вдавливания Возникает при неправильном отступе.
TabError Возникает, если отступ состоит из несовместимых табуляции и пробелов.
Ошибка системы Возникает, когда интерпретатор обнаруживает внутреннюю ошибку.
Выход из системы Вызвано функцией sys.exit () .
Тип Ошибка Возникает, когда функция или операция применяется к объекту неправильного типа.
UnboundLocalError Возникает, когда делается ссылка на локальную переменную в функции или методе, но к этой переменной не привязано никакого значения.
UnicodeError Возникает, когда возникает ошибка кодирования или декодирования, связанная с Unicode.
UnicodeEncodeError Возникает, когда во время кодирования возникает ошибка, связанная с Unicode.
UnicodeDecodeError Возникает, когда во время декодирования возникает ошибка, связанная с Unicode.
UnicodeTranslateError Возникает, когда во время перевода возникает ошибка, связанная с Unicode.
ValueError Возникает, когда функция получает аргумент правильного типа, но неправильное значение.
ZeroDivisionError Возникает, когда второй операнд деления или операции по модулю равен нулю.

При необходимости мы также можем определить собственные исключения в Python. Чтобы узнать о них больше, посетите Пользовательские исключения Python.

Мы можем обрабатывать эти встроенные и определяемые пользователем исключения в Python с помощью операторов try , , кроме и finally . Чтобы узнать о них больше, посетите инструкции Python try, except и finally.

.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *