Ошибка времени исполнения питон

In this article, we will look at some examples of runtime errors in Python Programming Language

Runtime Errors

  • A runtime error in a program is one that occurs after the program has been successfully compiled.

  • The Python interpreter will run a program if it is syntactically correct (free of syntax errors). However, if the program encounters a runtime error — a problem that was not detected when the program was parsed and is only revealed when a specific line is executed — it may exit unexpectedly during execution. When a program crashes due to a runtime error, we say it has crashed

Some examples of Python Runtime errors

  • division by zero

  • performing an operation on incompatible types

  • using an identifier that has not been defined

  • accessing a list element, dictionary value, or object attribute which doesn’t exist

  • trying to access a file that doesn’t exist

Let’s take a closer look at each of them by using an example

Division by zero

If we divide any number by zero, we get this error.

Algorithm (Steps)

Following are the Algorithm/steps to be followed to perform the desired task −

  • Take a variable to store the first input number.

  • Take another variable to store the second input number(Here the second number should be 0).

  • Divide the first number by the second number and print the result.

Example

The following program returns the runtime error if we divide a number with zero −

firstNumb = 11 secondNumb = 0 print(firstNumb/secondNumb)

Output

On executing, the above program will generate the following output −

Traceback (most recent call last):
  File "main.py", line 6, in <module>
print(firstNumb/secondNumb)
ZeroDivisionError: division by zero

Because the second number is 0 and no number can be divided by 0, we get a runtime
error.

Performing an operation on incompatible types

This error occurs when we perform operations like addition, multiplication, and so on on incompatible data types.

Algorithm (Steps)

Following are the Algorithm/steps to be followed to perform the desired task −

  • Take a string and assign some random value to it and store it in a variable.

  • Take an integer and assign some random integer value to it and store it in another variable.

  • Perform some operations such as addition on the above variables and print it.

Example

The following program returns the runtime error if we perform operation on incompatible data types −

inputString = "TutorialsPoint" inputNumber = 11 print(inputString + inputNumber)

Output

On executing, the above program will generate the following output −

Traceback (most recent call last):
  File "main.py", line 6, in <module>
    print(inputString + inputNumber)
TypeError: must be str, not int

We can’t add an integer to the string data type here, so we get a type error (runtime error).

Using an identifier that has not been defined

This error occurs when we attempt to access an identifier that has not been declared previously.

Example

The following program returns the runtime error if we are using undefined identifier −

print(tutorialsPoint)

Output

On executing, the above program will generate the following output −

Traceback (most recent call last):
  File "main.py", line 2, in <module>
    print(tutorialsPoint)
NameError: name 'tutorialsPoint' is not defined

Because we did not define the tutorialsPoint identifier and are accessing it by printing it, a runtime error occurs (Name error).

Accessing a list element, dictionary value, or object attribute which doesn’t exist

This runtime error occurs when we attempt to access a non-existent list,string,dictionary element/index.

When we attempt to use an index that does not exist or is too large, it throws an IndexError.

Algorithm (Steps)

Following are the Algorithm/steps to be followed to perform the desired task −

  • Create a list and assign some random values to it.

  • Access the list element by index by giving the index that doesn’t exist and printing it.

Example

The following program returns the index error if we access an element out of range −

inputList =[1, 4, 8, 6, 2] print("Element at index 10:", inputList[10])

Output

On executing, the above program will generate the following output −

Traceback (most recent call last):
  File "main.py", line 6, in <module>
    print("Element at index 10:", inputList[10])
IndexError: list index out of range

There are 5 elements in the list, and we are attempting to access the 10th index, which does not exist, resulting in an index error.

Trying to access a file that doesn’t exist

If we try to open a file that doesn’t exist, it throws a runtime error.

Algorithm (Steps)

Following are the Algorithm/steps to be followed to perform the desired task −

  • Create a variable to store the path of the text file. This is a fixed value. In the example below, this value must be substituted with the file path from your own system.

  • Use the open() function(opens a file and returns a file object as a result) to open the text file in read-only mode by passing the file name, and mode as arguments to it (Here “r” represents read-only mode)

givenFile = open(inputFile,"r")
  • Print it value of the given file.

Example

The following program returns the file not found error if we access an file that doesn’t exist −

inputFile = "tutorialsPoint.txt" givenFile = open(inputFile,"r") print(givenFile)

Output

On executing, the above program will generate the following output −

Traceback (most recent call last):
  File "main.py", line 4, in <module>
    givenFile = open(inputFile,"r")
FileNotFoundError: [Errno 2] No such file or directory: 'tutorialsPoint.txt'

Conclusion

We learned about runtime errors in Python in this article. We also used examples to explain the most common Python runtime errors.

  • Related Articles
  • Are Python Exceptions runtime errors?
  • What are runtime errors in JavaScript?
  • Difference between Compile Time Errors and Runtime Errors in C Program
  • Database Handling Errors in Python
  • Errors in Assessment
  • Runtime Polymorphism in Java
  • PHP Types of Errors
  • How can we define a Python function at runtime?
  • How to install and import Python modules at runtime?
  • Errors in C/C++
  • PHP Errors in PHP7
  • Custom Errors in JavaScript
  • Handling Errors in TypeScript
  • What are common programming errors or ‘gotchas’ in Python?
  • Runtime JAR File in Java
Kickstart Your Career

Get certified by completing the course

Get Started

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

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

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

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

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

Таким образом, runtime error в Python могут возникать по разным причинам, но существуют способы их исправления. Главное — быть внимательным и тщательно анализировать код при возникновении ошибок. Только так можно уверенно писать программы на Python и избежать непредсказуемого поведения программы.

Содержание

  1. Runtime error в Python: что это такое и как исправить
  2. Причины возникновения runtime error в Python
  3. Способы исправления runtime error в Python
  4. 1. Проверка типов данных
  5. 2. Обработка исключений
  6. 3. Проверка входных данных
  7. 4. Документирование кода
  8. 5. Использование отладчика
  9. 6. Перепроверка логики кода

Runtime error в Python: что это такое и как исправить

Runtime error (или ошибка времени выполнения) в Python возникает, когда программа запускается, но происходит некоторая ошибка, которая приводит к непредвиденному поведению программы или к ее аварийному завершению.

Ошибки времени выполнения могут возникать по разным причинам:

  1. Синтаксические ошибки: неправильная запись кода, отсутствие необходимых символов или неправильное использование знаков препинания.
  2. Логические ошибки: неправильное понимание алгоритма и логики выполнения программы.
  3. Неверные входные данные: передача некорректных данных или неправильное использование внешних библиотек и модулей.
  4. Проблемы с памятью: переполнение стека вызовов, выделение слишком большого объема памяти или неправильное использование указателей.

Для исправления ошибок времени выполнения в Python можно использовать следующие подходы:

  • Отладка (Debugging): использование IDE или инструментов для обнаружения и исправления ошибок в коде.
  • Обработка исключений (Exception handling): использование конструкций try/except для перехвата и обработки исключительных ситуаций.
  • Проверка входных данных: проверка входных данных на корректность перед их использованием в программе.
  • Тестирование (Testing): создание набора тестовых данных для проверки функциональности программы.
  • Использование статического анализатора кода: использование инструментов, позволяющих производить анализ кода на предмет обнаружения потенциальных ошибок.

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

Причины возникновения runtime error в Python

Runtime error или ошибка времени выполнения является одним из типов ошибок, которые могут возникнуть при выполнении программы на языке Python. Такая ошибка возникает во время работы программы, когда происходит нарушение правил исполнения кода.

Ошибки времени выполнения могут быть вызваны различными факторами, включая:

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

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

Примеры runtime error в Python:

Ошибка Описание
NameError Использование неопределенной переменной.
TypeError Неправильное использование типов данных.
ZeroDivisionError Деление на ноль.
IndexError Обращение к несуществующему индексу списка.

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

Способы исправления runtime error в Python

Ошибки времени выполнения (runtime error) в Python могут возникать по разным причинам. Их исправление зависит от конкретной ошибки и ситуации. В данной статье мы рассмотрим некоторые способы исправления наиболее распространенных ошибок времени выполнения в Python.

1. Проверка типов данных

Одной из самых частых причин возникновения runtime error является неправильное использование типов данных. Для избежания этой проблемы важно проводить проверку типов данных перед выполнением операций. Для этого можно использовать функции, такие как isinstance(), type() и другие.

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

Использование конструкции try-except поможет обрабатывать возможные исключения и предотвратит возникновение runtime error в Python. Оператор try используется для обозначения блока кода, в котором может произойти исключение. Оператор except указывает, как обработать это исключение.

3. Проверка входных данных

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

4. Документирование кода

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

5. Использование отладчика

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

6. Перепроверка логики кода

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

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

A runtime error is a type of error that occurs during program execution. The Python interpreter executes a script if it is syntactically correct. However, if it encounters an issue at runtime, which is not detected when the script is parsed, script execution may halt unexpectedly.

What Causes Runtime Errors

Some of the most common examples of runtime errors in Python are:

  • Division by zero.
  • Using an undefined variable or function name.
  • Performing an operation on incompatible types.
  • Accessing a list element, dictionary key or object attribute that does not exist.
  • Accessing a file that does not exist.

Python Runtime Error Examples

Here’s a few examples of runtime errors in Python:

Division by zero

If a number is divided by zero in Python, a runtime error is raised:

print(100/0)

In the above example, a number is attempted to be divided by zero. Running the above code raises a ZeroDivisionError:

Traceback (most recent call last):
  File "main.py", line 1, in <module>
    print(100/0)
ZeroDivisionError: division by zero

Using an undefined variable or function name

A runtime error is raised if an attempt is made to access an identifier, such as a variable or function name, that is not declared previously:

print(myString)

In the above example, an undefined identifier myString is attempted to be accessed. Running the above code raises a NameError:

Traceback (most recent call last):
  File "main.py", line 1, in <module>
    print(myString)
NameError: name 'myString' is not defined

Performing an operation on incompatible types

If an operation, such as addition, multiplication etc., is performed between incompatible data types, a runtime error is raised:

myString = "Hello World"
myNumber = 100
print(myString + myNumber)

In the above example, a string is attempted to be concatenated with a number. Since these types are incompatible, a TypeError is raised when the above code is executed:

File "main.py", line 3, in <module>
    print(myString + myNumber)
TypeError: can only concatenate str (not "int") to str

Accessing a non-existent list element, dictionary key or object attribute

If an attempt is made to access a non-existent index or element in a list, dictionary or   object, a runtime error is raised.

numbers = [1, 2, 3]
print(numbers[3])

In the above example, an attempt is made to access an item in a list using an out-of-range index, which raises an IndexError:

Traceback (most recent call last):
  File "main.py", line 2, in <module>
    print(numbers[3])
IndexError: list index out of range.

Accessing a file that does not exist

If a file that does not exist is attempted to be accessed, a runtime error is raised:

open("myFile.txt", "r")

In the above example, a non-existent file myFile.txt is attempted to be opened in read-only mode, which raises a FileNotFoundError:

Traceback (most recent call last):
  File "main.py", line 1, in <module>
    open("myFile.txt", "r")
FileNotFoundError: [Errno 2] No such file or directory: 'myFile.txt'

How to Fix Runtime Errors in Python

To fix runtime errors in Python, the following steps can be taken:

  1. Identify the error message and note the specific problem being reported.
  2. Check the code for logical, mathematical or typographical errors.
  3. Ensure all identifiers are defined properly before being used.
  4. Make sure the correct data types are being used and are being used correctly.
  5. Verify that list items, dictionary keys, and other objects are being accessed using valid indices or keys.
  6. If necessary, consult the documentation for the relevant library or module.

Track, Analyze and Manage Errors With Rollbar

Managing errors and exceptions in your code is challenging. It can make deploying production code an unnerving experience. Being able to track, analyze, and manage errors in real-time can help you to proceed with more confidence. Rollbar automates error monitoring and triaging, making fixing Python errors easier than ever. Try it today!

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

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

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

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

Содержание

  1. Сплошные ошибки выполнения в Python: их происхождение и способы решения
  2. Как и почему возникают ошибки выполнения в Python?
  3. Основные причины появления ошибок выполнения
  4. Как исправить ошибки выполнения в Python?
  5. 1. Анализ трассировки стека
  6. 2. Профилирование кода
  7. 3. Отладка с помощью блоков try-except
  8. 4. Тестирование программы
  9. Заключение

Сплошные ошибки выполнения в Python: их происхождение и способы решения

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

Одной из наиболее распространенных ошибок исполнения является ZeroDivisionError, которая возникает, когда происходит попытка деления на ноль:


num1 = 10
num2 = 0
result = num1 / num2 # ZeroDivisionError: division by zero

Другой часто встречающейся ошибкой исполнения является IndexError, которая возникает, когда обращаемся к несуществующему индексу в списке или кортеже:


fruits = ['apple', 'banana', 'orange']
print(fruits[3]) # IndexError: list index out of range

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


num = 10
text = 'apple'
result = num + text # TypeError: unsupported operand type(s) for +: 'int' and 'str'

Для решения ошибок выполнения в Python следует исправить их исходные причины. В случае ZeroDivisionError можно добавить проверку на ноль перед делением или использовать обработку исключения:


num1 = 10
num2 = 0
if num2 != 0:
result = num1 / num2
else:
result = 0

Для решения IndexError следует проверить, что индекс находится в допустимом диапазоне:


fruits = ['apple', 'banana', 'orange']
if len(fruits) > 3:
print(fruits[3])
else:
print("The index is out of range")

Для решения TypeError следует убедиться, что операнды имеют совместимые типы или преобразовать их в совместимый тип:


num = 10
text = 'apple'
combined = str(num) + text

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

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

Как и почему возникают ошибки выполнения в Python?

Ошибки выполнения, или runtime error, возникают в Python, когда программа не может выполнять определенные инструкции из-за некорректных данных или неправильной структуры кода.

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

  • Неправильные типы данных: Python строго типизированный язык программирования, поэтому если вы пытаетесь использовать переменную определенного типа данных в неправильном контексте, возникнет ошибка выполнения. Например, попытка деления строки на число вызовет ошибку, так как операция деления не применима к строкам.
  • Отсутствие необходимых модулей или библиотек: Если вы пытаетесь использовать модуль или библиотеку, которая не установлена или не импортирована в вашей программе, это вызовет ошибку выполнения. В таком случае вам нужно установить и импортировать соответствующий модуль или библиотеку.
  • Ошибки синтаксиса: Ошибки синтаксиса возникают, когда у вас есть неправильная структура кода, которую Python не может понять. Это может быть неправильное использование ключевых слов, пропущенная или лишняя скобка, апостроф или кавычка и т. д. В таких случаях необходимо внимательно проверить код и исправить ошибку.
  • Деление на ноль: Попытка деления на ноль является математической ошибкой и вызывает ошибку выполнения. Python не позволяет делить на ноль, поэтому необходимо убедиться, что вы правильно используете операцию деления в своей программе.
  • Отсутствие доступа к файлам или ресурсам: Если ваша программа пытается получить доступ к файлам или ресурсам, к которым у нее нет права доступа, например, отсутствует файл или директория, это вызовет ошибку выполнения. В таких случаях необходимо убедиться, что файл или ресурс существует и ваша программа имеет права доступа к нему.

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

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

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

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

Ниже перечислены некоторые из основных причин появления ошибок выполнения:

  • Неправильное использование функций: Ошибка может возникать, если функция вызывается с неправильными аргументами или неправильным количеством аргументов. Это может быть вызвано незнанием правильного синтаксиса функции или некорректным использованием функционала.
  • Несоответствие типов данных: Python — строго типизированный язык, что означает, что значения переменных должны соответствовать своим типам данных. Если переменная содержит значение неправильного типа данных, это может вызвать ошибку выполнения.
  • Индексация за пределами массива: Ошибка может возникнуть, если пытаться получить доступ к элементу массива или списка по индексу, которого нет в диапазоне доступных индексов.
  • Деление на ноль: В Python деление на ноль является ошибкой выполнения, и это может произойти, если в программе есть деление на переменную со значением ноль.
  • Неиспользуемые или необъявленные переменные: Если переменная не была объявлена или если она была объявлена, но не была использована, это может вызвать ошибку выполнения.

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

Как исправить ошибки выполнения в Python?

Ошибки выполнения, известные как runtime error, могут возникнуть в программе на языке Python по разным причинам. Например, неправильное использование переменных, непредвиденные значения входных данных или неправильная логика программы. В этом разделе мы рассмотрим несколько способов исправить такие ошибки.

1. Анализ трассировки стека

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

2. Профилирование кода

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

3. Отладка с помощью блоков try-except

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

4. Тестирование программы

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

Заключение

Исправление ошибок выполнения в Python требует понимания причин возникновения ошибок и использования соответствующих методов. Анализ трассировки стека, профилирование кода, отладка с помощью блоков try-except и тестирование программы — все это полезные инструменты для исправления и предотвращения ошибок выполнения.

A runtime error is a type of error that occurs during program execution. The Python interpreter executes a script if it is syntactically correct. However, if it encounters an issue at runtime, which is not detected when the script is parsed, script execution may halt unexpectedly.

What Causes Runtime Errors

Some of the most common examples of runtime errors in Python are:

  • Division by zero.
  • Using an undefined variable or function name.
  • Performing an operation on incompatible types.
  • Accessing a list element, dictionary key or object attribute that does not exist.
  • Accessing a file that does not exist.

Python Runtime Error Examples

Here’s a few examples of runtime errors in Python:

Division by zero

If a number is divided by zero in Python, a runtime error is raised:

print(100/0)

In the above example, a number is attempted to be divided by zero. Running the above code raises a ZeroDivisionError:

Traceback (most recent call last):
  File "main.py", line 1, in <module>
    print(100/0)
ZeroDivisionError: division by zero

Using an undefined variable or function name

A runtime error is raised if an attempt is made to access an identifier, such as a variable or function name, that is not declared previously:

print(myString)

In the above example, an undefined identifier myString is attempted to be accessed. Running the above code raises a NameError:

Traceback (most recent call last):
  File "main.py", line 1, in <module>
    print(myString)
NameError: name 'myString' is not defined

Performing an operation on incompatible types

If an operation, such as addition, multiplication etc., is performed between incompatible data types, a runtime error is raised:

myString = "Hello World"
myNumber = 100
print(myString + myNumber)

In the above example, a string is attempted to be concatenated with a number. Since these types are incompatible, a TypeError is raised when the above code is executed:

File "main.py", line 3, in <module>
    print(myString + myNumber)
TypeError: can only concatenate str (not "int") to str

Accessing a non-existent list element, dictionary key or object attribute

If an attempt is made to access a non-existent index or element in a list, dictionary or   object, a runtime error is raised.

numbers = [1, 2, 3]
print(numbers[3])

In the above example, an attempt is made to access an item in a list using an out-of-range index, which raises an IndexError:

Traceback (most recent call last):
  File "main.py", line 2, in <module>
    print(numbers[3])
IndexError: list index out of range.

Accessing a file that does not exist

If a file that does not exist is attempted to be accessed, a runtime error is raised:

open("myFile.txt", "r")

In the above example, a non-existent file myFile.txt is attempted to be opened in read-only mode, which raises a FileNotFoundError:

Traceback (most recent call last):
  File "main.py", line 1, in <module>
    open("myFile.txt", "r")
FileNotFoundError: [Errno 2] No such file or directory: 'myFile.txt'

How to Fix Runtime Errors in Python

To fix runtime errors in Python, the following steps can be taken:

  1. Identify the error message and note the specific problem being reported.
  2. Check the code for logical, mathematical or typographical errors.
  3. Ensure all identifiers are defined properly before being used.
  4. Make sure the correct data types are being used and are being used correctly.
  5. Verify that list items, dictionary keys, and other objects are being accessed using valid indices or keys.
  6. If necessary, consult the documentation for the relevant library or module.

Track, Analyze and Manage Errors With Rollbar

Managing errors and exceptions in your code is challenging. It can make deploying production code an unnerving experience. Being able to track, analyze, and manage errors in real-time can help you to proceed with more confidence. Rollbar automates error monitoring and triaging, making fixing Python errors easier than ever. Try it today!

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

Содержание

  • Известные ошибки в ПО

    • 1962 г.: ракета Маринер-1

    • 1985 г.: аппарат лучевой терапии Therac-25

    • 1991 г.: ЗРК Patriot

    • 2000 г.: Проблема 2000 года (Y2K)

    • 2009-2011 г.: отзыв автомобилей Toyota

  • Определение и разновидности ошибок

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

    • Логические (семантические) ошибки

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

    • Недокументированное поведение

  • Поиск ошибок и отладка программы

  • Подходы к обработке ошибок

  • Обработка исключений в Python

    • Понятия исключения

    • Конструкция try

    • Возбуждение исключений (raise)

    • Особенности обработки исключений внутри функций

    • Утверждения (assert)

    • Исключения или утверждения?

  • Рекомендации

7.1.1. Известные ошибки в ПО¶

История знает множество примеров, где программные ошибки стоили не только огромных денег, но и человеческих жизней 6 7:

7.1.1.1. 1962 г.: ракета Маринер-1¶

Маринер-1 — космический аппарат США для изучения Венеры (Рисунок 7.1.1).

_images/07_01_01.png

Рисунок 7.1.1 — Ракета Маринер-1 9

  • Описание и причина:

    Программист сделал ошибку, когда переводил рукописные математические формулы в код. Символ логического отрицания ¬ он принял за минус, и это привело к тому, что ракета воспринимала нормальные скорости как критические и из-за этого сбилась с курса.

  • Примерный ущерб / потери

    Никто не погиб, однако экономические потери составили 18,3 млн. долларов.

7.1.1.2. 1985 г.: аппарат лучевой терапии Therac-25¶

Therac-25 — канадский аппарат лучевой терапии (Рисунок 7.1.2).

_images/07_01_02.png

Рисунок 7.1.2 — Аппарат лучевой терапии `Therac-25 10

  • Описание и причина:

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

  • Примерный ущерб / потери

    Умерло 2 человека, 4 получили серьезное облучение.

7.1.1.3. 1991 г.: ЗРК Patriot¶

Patriot — американский зенитный ракетный комплекс (Рисунок 7.1.3)

_images/07_01_03.png

Рисунок 7.1.3 — ЗРК Patriot 11

  • Описание и причина:

    Во время Войны в Персидском заливе по казармам подразделений США был нанесен ракетный удар иракскими ракетами типа Р-17 (советская баллистическая ракета). Ни одна из ракет не была перехвачена, и удар достиг цели.

    В программном обеспечении ЗРК, отвечающем за ведение и перехват цели, присутствовала ошибка, из-за которой со временем внутренние часы постепенно отходили от истинного значения времени: системное время хранилось как целое число в 24-битном регистре с точностью до 0,1 секунды; при итоговом расчете данные переводились в вещественное число.

    Проблема заключалась в том, что число (cfrac{1}{10}) не имеет точного представления в двоичной системе счисления:

    • (cfrac{1}{10}_{10} = 0,0001100110011001100110011001100…_{2});

    • (cfrac{1}{10}_{10} = 0,00011001100110011001100_{2}) (24-битное целое в системе Patriot);

    • ошибка 1 измерения: ~ (0,000000095_{10});

    • ошибка за 100 часов работы (0,000000095 cdot 10 cdot 60 cdot 60 cdot 100 = 0,34) с.;

    • ракета Р-17 летит со скоростью 1676 м/c, и проходит за 0,34 с. больше полукилометра.

    Данной ошибки в измерениях было достаточно, чтобы ракета преодолела радиус поражения Patriot (Рисунок 7.1.4, Видео 7.1.1).

    _images/07_01_04.png

    Рисунок 7.1.4 — Неправильное определение зоны пролета ракеты 12

    Видео 7.1.1 — Демонстрация ошибки ПО Patriot

  • Примерный ущерб / потери

    Погибло 28 американских солдат и еще двести получили ранения.

7.1.1.4. 2000 г.: Проблема 2000 года (Y2K)¶

  • Описание и причина:

    Разработчики программного обеспечения, выпущенного в XX веке, зачастую использовали два знака для представления года в датах: например, 1 января 1961 года представлялось как «01.01.61». При наступлении 1 января 2000 года при двузначном представлении года после 99 наступал 00 год (т.е. 99 + 1 = 00), что интерпретировалось многими старыми программами как 1900 год. Сложность была еще и в том, что многие программы обращались к вычислению дат вперед (например, при составлении плана закупок, планировании даты полета и т.д.) (Рисунок 7.1.5).

    _images/07_01_05.png

    Рисунок 7.1.5 — Табло показывает 3 января 1900 года, вместо 3 января 2000 года. Франция 13

  • Примерный ущерб / потери

    30-300 млрд. долларов.

7.1.1.5. 2009-2011 г.: отзыв автомобилей Toyota¶

  • Описание и причина:

    Неисправность в дроссельной заслонке (регулирует количество горючей смеси, поступающей в цилиндры двигателя внутреннего сгорания) с электронным контролем (ETC) приводила к случайным ускорениям автомобиля (Видео 7.1.2).

    Видео 7.1.2 — Случайное ускорение автомобиля

    В ходе десятимесячного расследования специалисты NASA выявили, что программное обеспечение не соответствует стандартам MISRA (англ. Motor Industry Software Reliability Association) и содержит 7134 нарушения. Представители Toyota ответили, что у них свои собственные стандарты.

    20 декабря 2010 года Тойота отвергнула обвинения, но выплатила 16 млрд. долларов в досудебном порядке по искам, выпустила обновление ПО для некоторых моделей машин и отозвала 5,5 млн. автомобилей 8 (Рисунок 7.1.6).

    _images/07_01_06.png

    Рисунок 7.1.6 — Lexus ES 350 2007-2010 — одна из моделей с неисправностью 14

  • Примерный ущерб / потери

    Погибло не менее 89 человек, многомиллиардные потери компании.

7.1.2. Определение и разновидности ошибок¶

Ошибка (также баг от англ. Software Bug) — неполадка в программе, из-за которой она ведет себя неопределенно, выдавая неожиданный результат.

Основные категории ошибок:

  • синтаксические;

  • логические;

  • ошибки времени выполнения;

  • недокументированное поведение.

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

  • Причина:

    Несоответствие синтаксису языка программирования. Для компилируемых языков программирования синтаксическая ошибка не позволит выполнить компиляцию.

  • Пример:

    >>> for i in range(10)
      File "<stdin>", line 1
        for i in range(10)
                         ^
    SyntaxError: invalid syntax
    

7.1.2.2. Логические (семантические) ошибки¶

  • Причина:

    Несоответствие правильной логике работы программы.

  • Пример:

    >>> def avg_of_2(a, b):
    ...     return a + b / 2
    ...
    >>> avg_of_2(4, 8)  # Вернет 8 вместо 6
    

7.1.2.3. Ошибки времени выполнения¶

  • Причина:

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

  • Пример:

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

7.1.2.4. Недокументированное поведение¶

  • Причина:

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

  • Пример:

    Одним из наиболее известных примеров являются SQL-инъекции — внедрение в запрос произвольного SQL-кода.

    -- Код на сервере
    txtUserId = getRequestString("UserId");
    txtSQL = "SELECT * FROM Users WHERE UserId = " + txtUserId;
    
    -- "Стандартный" вызов на клиенте при UserId = 105 сформирует запрос
    SELECT * FROM Users WHERE UserId = 105
    
    -- Передача в качестве 'UserId' значения
    -- "105; DROP TABLE Suppliers" приведет к удалению таблицы 'Suppliers'
    SELECT * FROM Users WHERE UserId = 105; DROP TABLE Suppliers
    

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

Видео 7.1.3 — Презентация ОС Windows 98

7.1.3. Поиск ошибок и отладка программы¶

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

Существуют две взаимодополняющие технологии отладки:

  • использование отладчиков: программ, которые включают в себя пользовательский интерфейс для пошагового выполнения программы: оператор за оператором, функция за функцией, с остановками на некоторых строках исходного кода или при достижении определенного условия (Рисунок 7.1.7);

    _images/07_01_07.png

    Рисунок 7.1.7 — Пример отладки в IDE PyCharm: выполнение «заморожено» на точке останова (англ. Breakpoint), при этом IDE отображает текущие значения переменных, дополнительные окна и параметры

  • вывод текущего состояния программы с помощью расположенных в критических точках программы операторов вывода — на экран, принтер, громкоговоритель или в файл. Вывод отладочных сведений в файл называется журналированием (также логгированием или аудитом) (Листинг 7.1.1).

    Листинг 7.1.1 — Пример отладочного вывода с использованием функции print() | скачать

    import random
    
    a = random.randint(1, 100)
    b = random.randint(1, 100)
    
    print(a, b)  # 44 97
    
    print(a**2 + b**2)  # 11345
    

7.1.4. Подходы к обработке ошибок¶

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

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

  1. «Семь раз отмерь, один раз отрежь» — LBYL (англ. Look Before You Leap);

    Суть подхода: прежде чем выполнить основное действие выполняются проверки — не получится ли деления на ноль, есть ли файл на диске и т.д.

  2. «Легче попросить прощения, чем разрешения» — EAFP (англ. «It’s Easier To Ask Forgiveness Than Permission»).

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

В Листинге 7.1.2 приведен пример сравнения двух подходов.

Листинг 7.1.2 — Псевдокод функций, использующих разные подходы к обработке ошибок: «Семь раз отмерь, один раз отрежь» и «Легче попросить прощения, чем разрешения»

Обе функции возвращают решение линейного уравнения и НИЧЕГО, если 'a' = 0


ФУНКЦИЯ найти_корень_1(a, b):
    ЕСЛИ a не равно 0
        ВЕРНУТЬ -b / a
    ИНАЧЕ
        ВЕРНУТЬ НИЧЕГО


ФУНКЦИЯ найти_корень_2(a, b):
    ОПАСНЫЙ БЛОК КОДА      # Внутри данного блока пишется код, который
        ВЕРНУТЬ -b / a     # потенциально может привести к ошибкам
    ЕСЛИ ПРОИЗОШЛА ОШИБКА  # В случае деления на 0 попадаем сюда
        ВЕРНУТЬ НИЧЕГО

Подход «Семь раз отмерь, один раз отрежь» имеет определенные минусы:

  • проверки могут уменьшить читаемость и ясность основного кода;

  • код проверки может дублировать значительную часть работы, осуществляемой основным кодом;

  • разработчик может легко допустить ошибку, забыв какую-либо из проверок;

  • ситуация может изменится между моментом проверки и моментом выполнения операции.

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

7.1.5. Обработка исключений в Python¶

7.1.5.1. Понятия исключения¶

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

  • BaseException (базовое исключение)

    • SystemExit (исключение, порождаемое функцией sys.exit() при выходе из программы)

    • KeyboardInterrupt (прерывании программы пользователем, Ctrl+C)

    • Exception (базовое несистемное исключение)

      • ArithmeticError (арифметическая ошибка)

        • FloatingPointError (неудачное выполнение операции с плавающей запятой)

        • OverflowError (результат арифметической операции слишком велик для представления)

        • ZeroDivisionError (деление на ноль)

      • LookupError (некорректный индекс или ключ)

        • IndexError (индекс не входит в диапазон элементов)

        • KeyError (несуществующий ключ)

      • MemoryError (недостаточно памяти)

      • NameError (не найдено переменной с таким именем)

      • OSError (ошибка, связанная с ОС — есть подклассы, например FileNotFoundError)

      • SyntaxError (синтаксическая ошибка, включает классы IndentationError и TabError)

      • SystemError (внутренняя ошибка)

      • TypeError (операция применена к объекту несоответствующего типа)

      • ValueError (аргумент правильного типа, но некорректного значения)

Пример встроенного возбуждения исключения:

>>> "я - строка" / 5
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for /: 'str' and 'int'

7.1.5.2. Конструкция try

Придерживаясь идеологии «Легче попросить прощения, чем разрешения», Python предусматривает конструкцию try для обработки возникающих исключений.

try
except
else
finally
try:                              # (try строго 1)
    try_ suite                    # код, который может выполниться с ошибкой
except exception_group1 as var1:  # (except - 0 (если есть finally) и более)
    except_suite1                 # код, выполняемый в случае исключения 'exception_group1'
...                               # ссылка на исключение может быть записана в 'var1'
except exception_groupN as varN:
    except_suiteN                 # код, выполняемый в случае исключения 'exception_groupN'
...                               # except-блоков может быть произвольное кол-во
else:                             # (else - 0 или 1)
    else_suite                    # выполняется, если try не завершен преждевременно (например, break)
finally:                          # (finally - 0 или 1)
    finally_suite                 # код, который должен выполнится всегда (была ошибка выше или нет)

Ход выполнения:

  • код, который потенциально может привести к ошибке, помещается в блок try;

  • в случае ошибки, код немедленно завершается и переходит в обработчик except (если он указан для соответствующего исключения);

  • после поток выполнения переходит к else (если исключений не было) и finally (в любом случае).

На Рисунке 7.1.8 приведены общие варианты потока выполнения программы при обработке исключений.

_images/07_01_08.png

Рисунок 7.1.8 — Варианты потока выполнения программы при обработке исключений 4

Обработка исключений (и соответственно идеология «Легче попросить прощения, чем разрешения») — предпочитаемый способ в Python, а использование блоков зависит от конкретной ситуации.

Наиболее общий вариант обработки исключений приведен в Листинге 7.1.3.

Листинг 7.1.3 — Наиболее простой способ обработки исключений | скачать

try:
    x = int(input("Введите целое число x (для вычисления 1/x): "))
    res = 1 / x

    print("1/{} = {:.2f}".format(x, res))
except:
    print("Произошла ошибка!")

# --------------
# Примеры вывода:

# Введите целое число x (для вычисления 1/x): 3
# 1/3 = 0.33

# Введите целое число x (для вычисления 1/x): qwerty
# Произошла ошибка!

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

Листинг 7.1.4 — Обработка общего класса исключений Exception | скачать

try:
    x = int(input("Введите целое число x (для вычисления 1/x): "))
    res = 1 / x

    print("1/{} = {:.2f}".format(x, res))
except Exception as err:
    print("Произошла ошибка!")
    print("Тип:", type(err))
    print("Описание:", err)

# --------------
# Примеры вывода:

# Введите целое число x (для вычисления 1/x): 3
# 1/3 = 0.33

# Введите целое число x (для вычисления 1/x): 5.5
# Произошла ошибка!
# Тип: <class 'ValueError'>
# Описание: invalid literal for int() with base 10: '5.5'

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

Листинг 7.1.5 — Обработка конкретных классов исключений | скачать

try:
    x = int(input("Введите целое число x (для вычисления 1/x): "))
    res = 1 / x

    print("1/{} = {:.2f}".format(x, res))
except ZeroDivisionError:
    print("На ноль делить нельзя!")
except ValueError as err:  # 'err' содержит ссылку на исключение
    print("Будьте внимательны:", err)
except (FileExistsError, FileNotFoundError):  # Исключения можно перечислять в виде кортежа
    print("Этого никогда не случится - мы не работаем с файлами")
except Exception as err:
    # Все, что не обработано выше и является потомком 'Exception',
    # будет обработано здесь
    print("Произошла ошибка!")
    print("Тип:", type(err))
    print("Описание:", err)

# --------------
# Примеры вывода:

# Введите целое число x (для вычисления 1/x): 3
# 1/3 = 0.33

# Введите целое число x (для вычисления 1/x): 0
# На ноль делить нельзя!

# Введите целое число x (для вычисления 1/x): qwerty
# Будьте внимательны: invalid literal for int() with base 10: 'qwerty'

7.1.5.3. Возбуждение исключений (raise

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

raise
raise exception(args)  # явное указание класса возбуждаемого исключения

# или

raise                  # 1) повторное возбуждение активного исключения (re-raise)
                       #    внутри блока except
                       # 2) 'TypeError' по умолчанию

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

В Листинге 7.1.6 приведен пример использование оператора raise.

Листинг 7.1.6 — Использование raise для управления потоком выполнения | скачать

MIN = 1
MAX = 10

try:
    x = int(input("Введите целое число от {} до {}: ".format(MIN, MAX)))

    if not MIN <= x <= MAX:
        # Возбудив исключение, его можно будет обработать в except
        # вместе с другими похожими исключениями
        raise ValueError("Число лежит вне интервала [{}; {}]!".format(MIN, MAX))

    print("Спасибо!")
except ValueError as err:  # 'err' содержит ссылку на исключение
    print("Будьте внимательны:", err)

# --------------
# Примеры вывода:

# Введите целое число от 1 до 10: 5
# Спасибо!

# Введите целое число от 1 до 10: 15
# Будьте внимательны: Число лежит вне интервала [1; 10]!

# Введите целое число от 1 до 10: qwerty
# Будьте внимательны: invalid literal for int() with base 10: 'qwerty'

7.1.5.4. Особенности обработки исключений внутри функций¶

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

Разница в обработке исключений приведена в Листинге 7.1.7.

Листинг 7.1.7 — Различная обработка исключений в функции | скачать

# Ниже представлены 3 варианта обработки исключений в функциях
# Основное правило - обработка исключений внутри возможна и нужна, однако
#                    вызывающий код должен также знать о случившемся, если
#                    влияет на дальнейшую работу


def get_1_x(x):
    """Вернуть 1/x.

    Функция не обрабатывает исключения - ответственность на вызывающем коде.
    """
    return 1/x


def get_2_x(x):
    """Вернуть 2/x.

    Функция обрабатывает исключения, "затушив" ошибку - вызывающий код
    не будет знать, сработала функция правильно или нет.

    Данный способ использовать не рекомендуется!
    """
    try:
        return 2/x
    except Exception as e:
        print("Внутри произошла ошибка...", e)


def get_3_x(x):
    """Вернуть 3/x.

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

    Внутренняя обработка исключений может быть полезна, если в целом результат
    функции не связан с внутренней ошибкой.
    """
    try:
        return 3/x
    except Exception as e:
        print("Внутри произошла ошибка...", e)
        raise

funcs = (get_1_x, get_2_x, get_3_x)
# Вызываем каждую функцию с "ошибочным" параметром
for func in funcs:
    try:
        print("-" * 50)
        print("Запущена функция:", func.__name__)
        print(func(0))
    except Exception as e:
        print("Произошла ошибка: {}.".format(e))

# -------------
# Пример вывода:

# --------------------------------------------------
# Запущена функция: get_1_x
# Произошла ошибка: division by zero.
# --------------------------------------------------
# Запущена функция: get_2_x
# Внутри произошла ошибка... division by zero
# None
# --------------------------------------------------
# Запущена функция: get_3_x
# Внутри произошла ошибка... division by zero
# Произошла ошибка: division by zero.

7.1.5.5. Утверждения (assert

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

В Python утверждения поддерживаются оператором assert.

assert
assert boolean_expression[, optional_expression]

# boolean_expression: логическое выражение для проверки
# optional_expression: необязательное сообщение (строка)

Если boolean_expression возвращает False, возбуждается исключение AssertionError с сообщением optional_expression (если задано).

Пример использования утверждений приведен в Листинге 7.1.8.

Листинг 7.1.8 — Использование утверждений в Python | скачать

# Использование оператора assert
# поможет отследить неверно реализованную функцию


def add_to_list(x, lst=[]):
    # Использование assert здесь оправдано - список всегда
    # подразумевается пустым
    assert len(lst) == 0, "Список должен быть пуст!"

    lst.append(x)
    return lst


print(add_to_list(1))
print(add_to_list(2))

# -------------
# Пример вывода:

# [1]
# Traceback (most recent call last):
#   File "07_01_08_a.py", line 15, in <module>
#     print(add_to_list(2))
#   File "07_01_08_a.py", line 8, in add_to_list
#     assert len(lst) == 0, "Список должен быть пуст!"
# AssertionError: Список должен быть пуст!

Примечание

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

7.1.5.6. Исключения или утверждения?¶

При выборе, использовать исключения или утверждения, придерживайтесь правил (Таблица 7.1.1).

Таблица 7.1.1 — Использовать исключения или утверждения?

Исключения

Утверждения

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

Проверка ситуаций, которые предположительно не могут произойти

1

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

Проверка предусловий, постусловий и инвариантов в необщедоступном коде (локальных функциях, внутреннем коде и т.д.)

2

Предоставление информации об ошибке пользователю

Предоставление информации об ошибке команде разработки

3

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

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

Примеры использования исключения и утверждений приведены в Листингах 7.1.9 (а-в).

Листинг 7.1.9 (а) — Использование исключений и утверждений в Python | скачать

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


def fact(x):
    """Вернуть факториал 'x'.

    Не передавайте числа больше 15 во избежание переполнения памяти.
    """
    if x <= 1:
        return 1
    else:
        return x * fact(x-1)


def fact_save_1(x):
    assert x <= 15, 
        "Не передавайте числа больше 15 во избежание переполнения памяти"

    return fact(x)


def fact_save_2(x):
    if not x <= 15:
        raise ValueError("Не передавайте числа больше 15 во избежание "
                         "переполнения памяти")

    return fact(x)


print("{:>3} {:>20} {:>20}".format(*("x", "fact()", "fact_save()")))
for x in (5, 20):
    print("{:3}".format(x), end=" ")
    print("{:20}".format(fact(x)), end=" ")
    # print("{:20}".format(fact_save_1(x)))
    print("{:20}".format(fact_save_2(x)))

# -------------
# Пример вывода:

#   x               fact()          fact_save()
#   5                  120                  120
#  20  2432902008176640000 Traceback (most recent call last):
#   File "07_01_08_b.py", line 23, in <module>
#     print("{:20}".format(fact_save(x)))
#   File "07_01_08_b.py", line 15, in fact_save
#     assert x <= 15, "Не передавайте числа больше 15 во избежание переполнения памяти"
# AssertionError: Не передавайте числа больше 15 во избежание переполнения памяти
#
#   x               fact()          fact_save()
#   5                  120                  120
#  20  2432902008176640000 Traceback (most recent call last):
#   File "07_01_08_b.py", line 34, in <module>
#     print("{:20}".format(fact_save_2(x)))
#   File "07_01_08_b.py", line 24, in fact_save_2
#     raise ValueError("Не передавайте числа больше 15 во избежание "
# ValueError: Не передавайте числа больше 15 во избежание переполнения памяти

Листинг 7.1.9 (б) — Использование исключений и утверждений в Python | скачать

# Использование оператора assert для проверки входных и выходных данных


def make_call(accounts, account_id, mins, costs_per_min):
    """Списать со счета 'account' на 'value' баллов в случае звонка.

    Параметры:
        - accounts (dict): словарь со всеми счетами абонентов;
        - account_id (int): идентификатор абонента в словаре 'accounts';
        - mins (int): количество минут разговора;
        - costs_per_min (int): стоимость минуты разговора.
    """

    def get_costs(mins, costs_per_min):
        """Вернуть стоимость звонка.

        Параметры:
            - mins (int): количество минут разговора;
            - costs_per_min (int): стоимость минуты разговора.
        """
        return -mins * costs_per_min

    # Проверка типов
    assert isinstance(mins, int), "Параметр 'mins' имеет неверный тип!"
    assert isinstance(costs_per_min, (int, float)),
        "Параметр 'costs_per_min' имеет неверный тип!"

    # Проверка значений
    assert mins > 0, "Параметр 'mins' должен быть > 0"
    assert costs_per_min >= 0, "Параметр 'costs' должен быть >= 0"

    # Расчет (стоимость звонка не должна быть меньше 0)
    costs_total = get_costs(mins, costs_per_min)
    assert costs_total >= 0,
        "Расчет стоимости звонка был осуществлен неверно!"
    accounts[account_id] -= costs_total


# Словарь ID=Баланс
accounts = {"Василий Иванов": 100}
print(accounts)

try:
    make_call(accounts, "Василий Иванов", mins=4, costs_per_min=2)
except Exception as e:
    print("Во время списывания стоимости звонка произошла ошибка:", e)

print(accounts)

Листинг 7.1.9 (в) — Использование исключений и утверждений в Python | скачать

# Совместное использование исключений и утверждений

weekday_names = {
    1: "Понедельник",
    2: "Вторник",
    3: "Среда",
    4: "Четверг",
    5: "Пятница",
    6: "Суббота",
    7: "Воскресенье"
}


def weekday_name(weekday):
    """Вернуть название дня недели. Нумерация с 1.

    Параметры:
        weekday (int): номер дня недели.

    Исключения:
        - TypeError: 'weekday' не int;
        - ValueError: 'weekday' не число от 1 до 7.

    Результат:
        str: название дня недели.
    """
    # "Невозможная" ситуация - словарь 'weekday_names' может быть
    # "испорчен" - проверяется с помощью assert.
    assert weekday_names is not None and isinstance(weekday_names, dict), 
        "Внутренняя ошибка программы. Обратитесь в разрабочику."

    # Параметры функции проверяются с помощью исключений
    if not isinstance(weekday, int):
        raise TypeError("Параметр 'weekday' должен быть типа 'int'.")
    if weekday not in weekday_names:
        raise ValueError("Параметр 'weekday' должен быть целым числом "
                         "от 1 до 7.")

    return weekday_names[weekday]


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

while True:
    try:
        weekday = int(input("Введите номер дня недели (1-7): "))

        # if not 1 <= weekday <= 7:
        #     raise ValueError("Номер дня недели должен быть целым числом "
        #                      "от 1 до 7.")

        # Раскомментируйте код ниже, чтобы получить срабатывание assert
        # weekday_names = None

        print("Это -", weekday_name(weekday))

        break
    except TypeError as err:
        print("Проверьте, что введено целое число.")
    except ValueError as err:
        print("Проверьте, что введено целое число, и оно "
              "находится в допустимых границах.")
    except Exception as err:
        print("Ошибка при определении названия дня недели.")
        print(err)  # Запись в лог информации об ошибке

7.1.6. Рекомендации¶

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

  • код, который потенциально может привести к ошибкам, должен быть помещен в блок try;

  • блок except должен:

    • обрабатывать исключения максимально конкретно (указывать конкретные классы); стоит определять свои классы исключений, когда это это имеет смысл;

    • категорически не следует «тушить» исключения (писать пустой или бессмысленный except);

    • в блоках except следует снова возбуждать исключения (raise), которые не обрабатываются явно, передавая обработку в участок кода, который должен определять дальнейшие действия программы;

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


1

Sebesta, W.S Concepts of Programming languages. 10E; ISBN 978-0133943023.

2

Python — официальный сайт. URL: https://www.python.org/.

3

Python — FAQ. URL: https://docs.python.org/3/faq/programming.html.

4

Саммерфилд М. Программирование на Python 3. Подробное руководство. — М.: Символ-Плюс, 2009. — 608 с.: ISBN: 978-5-93286-161-5.

5

Лучано Рамальо. Python. К вершинам мастерства. — М.: ДМК Пресс , 2016. — 768 с.: ISBN: 978-5-97060-384-0, 978-1-491-94600-8.

6

5 худших багов в истории. URL: https://tproger.ru/articles/5-worst-bugs-in-history/.

7

List of software bugs. URL: https://en.wikipedia.org/wiki/List_of_software_bugs.

8

Toyota: 81 514 нарушений в коде. URL: https://habrahabr.ru/company/pvs-studio/blog/310862/.

9

Mariner-1. URL: https://ru.wikipedia.org/wiki/%D0%9C%D0%B0%D1%80%D0%B8%D0%BD%D0%B5%D1%80-1#/media/File:Atlas_Agena_with_Mariner_1.jpg.

10

Therac-25. URL: https://upload.wikimedia.org/wikipedia/commons/b/bd/Clinac_2rtg.jpg.

11

ЗРК Patriot. URL: http://vpk.name/file/img/Patriot_antimissile.t.jpg.

12

Incorrectly Calculated Range Gate. URL: https://hsto.org/files/853/04a/1dc/85304a1dc1b6499d94d5394436e42faf.jpg.

13

Табло показывает 3 января 1900 года, вместо 3 января 2000 года. Франция. URL: https://upload.wikimedia.org/wikipedia/commons/f/fb/Bug_de_l%27an_2000.jpg.

14

MY 2007–2010 Lexus ES 350. URL: http://pictures.topspeed.com/IMG/crop/201108/lexus-es-350-6_1600x0w.jpg.

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

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

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

  • Диск может быть заполнен во время записи данных в файлы и препятствовать дальнейшей записи.
  • Неожиданно обрушилась сеть во время загрузки той или иной информации.
  • Использование 0 в знаменателе при делении.

Разница между ошибкой и исключением

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

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

Типы ошибок

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

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

Блок кода:

num1 = 2
num2 = 3
Num3 = num1 num2
print(num3)

Вывод:

Ошибка нехватки памяти

Если вы получаете сообщение об ошибке памяти, вашему программному обеспечению не хватает памяти. Это говорит о том, что ваше ПО создает слишком много объектов. Memory Error сигнализирует о нехватке доступной памяти для выделения интерпретатором вашему приложению Python. Это может быть проблемой конфигурирования Python или проблемой, связанной с функцией загрузки многих конкурирующих за ресурсы данных.

Ошибка рекурсии

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

Блок кода:

def abc():
return abc()
abc()

Вывод:

Ошибка отступа

Python является процедурным языком, поэтому если вы не поместите табулятор или пробелы между строкам вашего кода, то, вероятно, получите ошибку Indentation Error.

Блок кода:

for i in range(3):
print(i)

Вывод:

Вы можете с удобством обслуживать исключения, благодаря встроенной в Python системе обработки исключений. Это механизм try…except…finally.

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

Обычные типы исключений в Python

Ошибка атрибута

Ошибки, связанные со ссылками на атрибуты или присвоением.

Блок кода:

arr = [1,2,3,4,5]
arr.len()

Вывод:

Ошибка индекса

Ошибка возникает, когда индекс последовательности выходит за границы.

Блок кода:

arr = [1,2,3,4,5]
print(arr[200])

Ошибка деления на нуль

Когда целое делится на 0, возникает Zero Division Error.

Блок кода:

arr = 1
arr = 0
print(a/b)

Вывод:

Ошибка типа

Эта ошибка возникает, когда в операции или методе используется объект неправильного типа.

Блок кода:

arr = [1,2,3,4,5]
arr.insert(1)

Вывод:

Ошибка значения

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

Блок кода:

import math
math.sqrt(-33)

Вывод:

Ошибка имени

Эта ошибка возникает, когда идентификатор не находится ни в локальном, ни в глобальном пространстве имен.

Блок кода:

print(Num)

Вывод:

Ошибка ключа

Эта ошибка возникает, когда словарь не включает заданный ключ.

Блок кода:

dic={"name":"achyut","age":20}
print(dic["value"])

Вывод:

Ошибка импорта

Эта ошибка возникает, когда модуль не может быть загружен оператором import.

Блок кода:

from math import add

Вывод:

Предложение Try и оператор Except

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

Синтаксис

try:
#возможный блок кода, который может вызвать исключение
except Exception:
#Код, который реагирует на возникающую ошибку

Замечание. Один блок try может обрабатывать множество блоков except для различных исключений.

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

Пример

a = input ("enter the Numerator:")
b = input ("enter the Denominator:")
try:
res = int(a) / int(b)
print ('result is:', res)
except ZeroDivisionError as e:
print ('exception is:', e)

Вывод:

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

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

Try с предложением Finally

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

Пример блока Finally

Блок кода:

a = input ("enter the Numerator:")
b = input ("enter the Denominator:")
try:
res = int(a) / int(b)
print ('result is:', res)
except ZeroDivisionError as e:
print ('exception is:', e)
finally:
print ("thank you")

Вывод:

Try с предложением Else

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

Пример блока Else

Блок кода:

a = input ("enter the Numerator:")
b = input ("enter the Denominator:")
try:
res = int(a) / int(b)
print ('result is:', res)
except ZeroDivisionError as e:
print ('exception is :', e)
else:
print("hello")
finally:
print ("thank you")

Вывод:

Захват конкретных исключений в Python

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

Пример

Блок кода:

def name_exception():
try:
value = "achyut tripathi"
return xyz
except NameError:
return "NameError occurred"

print(name_exception())

Вывод:

Вызов исключения в Python

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

Пример

Создадим небольшую функцию, которая ожидает число между 1 и 50. Если функция получает значение за пределами этого диапазона, работа приложения будет прервана с помощью пользовательского исключения.

Блок кода:

def range_function(range):
try:
if range > 50 or range <0:
raise Exception()
if range < 100 and range > 0:
print("Range is ok")
except:
print("Exception Occurred")
range_function(150)

Вывод:

Заключение

Примеры в этом руководстве показывают как использовать в Python блок «try-except-finally».

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

Отладка¶

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

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

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

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

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

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

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

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

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

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

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

Не могу запустить программу, что бы я ни делал¶

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

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

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

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

Моя программа совсем ничего не делает¶

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

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

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

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

  1. Если вы подозреваете какой-то определенный цикл, то добавьте предложение
    print непосредственно перед циклом, которое сообщит о входе в цикл, и
    еще одно сразу после цикла, сообщающее о выходе из него.
  2. Запустите программу. Если вы видите первое сообщение, но не видите второго,
    то программа вошла в бесконечный цикл. См. раздел Бесконечный цикл ниже.
  3. Что касается неограниченной рекурсии, то в этом случае программа будет выполняться
    какое-то время, пока не выдаст ошибку RuntimeError: Maximum recursion depth exceeded.
    Если это случилось, см. раздел Неограниченная рекурсия ниже.
  4. Если программа не выдает такую ошибку, но вы подозреваете, что проблема в
    рекурсивном методе или функции, приемы, описанные в разделе Неограниченная рекурсия,
    все же могут оказаться полезны.
  5. Если вышеописанные шаги не работают, проверьте другие циклы или другие рекурсивные
    функции и методы.
  6. Если и это не помогает, то вы, вероятно, не понимаете последовательность
    выполнения предложений в вашей программе. См. раздел Поток выполнения ниже.

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

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

Например:

while x > 0 and y < 0:
    # do something to x
    # do something to y

    print  "x: ", x
    print  "y: ", y
    print  "condition: ", (x > 0 and y < 0)

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

Неограниченная рекурсия¶

В большинстве случаев неограниченная рекурсия приведет к ошибке RuntimeError: Maximum recursion depth exceeded.

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

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

Поток выполнения¶

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

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

При выполнении программы возникает исключение¶

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

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

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

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

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

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

Слишком много данных выводится на печать¶

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

Чтобы упростить выводимые данные, можно удалить или закомментировать предложения print, которые уже не нужны, либо объединить отдельные print в один и отформатировать выводимые данные для более легкого восприятия.

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

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

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

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

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

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

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

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

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

Спросите себя:

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

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

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

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

Мое длинное выражение не работает¶

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

Пример:

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

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

neighbor = self.findNeighbor (i)
pickedCard = self.hands[neighbor].popCard()
self.hands[i].addCard (pickedCard)

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

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

Это неправильно. Операции умножения и деления имеют одинаковый приоритет, и их вычисление производится слева направо. Поэтому данное выражение на Python вычисляет (x/2)pi.

Отличный способ избавиться от подобных ошибок — явно обозначить порядок вычисления с помощью скобок:

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

Моя функция (или метод) возвращает не то, что мне нужно¶

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

return self.hands[i].removeMatches()

напишите:

count = self.hands[i].removeMatches()
return count

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

Ничего не понимаю, бред какой-то¶

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

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

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

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

Нет, мне реально нужна помощь¶

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

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

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

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

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

И помните, ваша цель не только в том, чтобы сделать работающую программу. Цель еще и в том, чтобы учиться делать работающие программы.

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

Интерпретатор Python создает исключение, когда обнаруживает ошибку времени выполнения, например, деление на ноль. Программа Python также может явно вызвать исключение с помощью инструкции raise. Обработчики исключений указываются с помощью оператора try ... except. Предложение finally такого оператора можно использовать для указания кода очистки, который не обрабатывает исключение, но выполняется независимо от того, произошло ли исключение в предыдущем коде.

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

Когда исключение вообще не обрабатывается, интерпретатор прекращает выполнение программы или возвращается к своему интерактивному основному циклу. В любом случае он печатает трассировку стека, кроме случаев, когда поднимается исключение SystemExit.

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

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

Смотрите также описание инструкции try ... except и заявления raise в разделе «Ошибки и исключения в Python»

Понравилась статья? Поделить с друзьями:
  • Ошибка входа lol
  • Ошибка времени исполнения паскаль
  • Ошибка вольво р0036
  • Ошибка входа league of legends
  • Ошибка времени выполнения питон