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

by Radu Tyrsina

Radu Tyrsina has been a Windows fan ever since he got his first PC, a Pentium III (a monster at that time). For most of the kids of… read more


Updated on

  • A run-time error happens when Python understands what you are saying, but runs into trouble when following your instructions.
  • You need to know that Python runs the program in two steps.
  • Not only Python features runtime errors and if you stumble across one, check our Runtime Errors Hub.
  • We wrote extensively about developer tools like Python. Go to our Developer tools Hub.

How to fix Python runtime error

XINSTALL BY CLICKING THE DOWNLOAD FILE

Get rid of malfunctioning drivers on your PC

SPONSORED

Drivers can often become corrupt as they can interfere with malfunctioning system files, thus arriving to be installed but not running correctly. To keep your drivers running smoothly, your Windows OS must run even smoother. Get it in perfect shape by following the steps below:

  1. Download Fortect and install it on your PC.
  2. Start the tool’s scanning process to look for corrupt files that are the source of your problem
  3. Right-click on Start Repair so the tool can start the fixing algorithm
  • Fortect has been downloaded by 0 readers this month, rated 4.4 on TrustPilot

Programming is pretty fun but at some point, when you try to run the program, unfortunately, and inevitably, errors will show up. So, causing, understanding, and fixing errors is an important part of programming.

There are three major types of error that you can get in Python but here we will talk about how to solve Python runtime errors.

A run-time error happens when Python understands what you are saying, but runs into trouble when following your instructions.


How can I fix Python runtime error?

So you’ve written everything correctly, in other words, your syntax is correct, but Python still doesn’t understand what you’re saying. Let’s have a simple example of a Python runtime error:

  • print(solution)

If you try to run this simple line, you will receive a runtime error simply because you didn’t define the solution variable. The line doesn’t have sense.

To understand better that conundrum, let’s make an association with English grammar. Let’s take this sentence for instance.

  • Please eat the door.

Grammatically, there is absolutely no problem with this sentence. Everything is there, we have all the syntax elements correct.

But when you are trying to understand the sentence, when you piece up the words, it doesn’t make sense because you know you can open and close the door, even shut it or taking it out but eating it?

In programming, this will be called a run-time error because it shows up before you start the program. There are a few types of runtime errors. In this article, you will learn how to solve them.

1. Use an undefined variable or function.

This can also occur if you use capital letters inconsistently in a variable name:

callMe = “Brad”
print(callme)

Traceback (most recent call last):
  In line 2 of the code you submitted:
    print(callme)
NameError: name 'callme' is not defined

In this case, the program returned the undefined variable error. You defined the variable callMe, but you try to print another variable, callme. You have to use the variables exactly as you define them, case sensitive.


2. Dividing by zero

Guess what? Python cares about math, and in math, dividing by zero makes no sense. 

print(1/0)

Traceback (most recent call last):
  In line 1 of the code you submitted:
    print(1/0)
ZeroDivisionError: division by zero

So this line returns a runtime error as Python can read it properly, but when it comes to executing it, he refuses to do so as it has no mathematical sense.


3. Use operators on the wrong type of data

print(“you are trying to add text and numbers” + 20)

Traceback (most recent call last):
  In line 1 of the code you submitted:
    print("you are trying to add text and numbers" + 20)
TypeError: can only concatenate str (not "int") to str

This line returns the runtime error because you try to add text with numbers, crayons, and oranges, chairs with pigeons, etc. It just doesn’t make sense to perform operations with different types of variables.

You also need to know that Python runs the program in two steps. It first checks the syntax and if the syntax is correct, it goes to the second step of executing the program. That’s where he stumbles on possible runtime errors.

We hope this guide answers all your questions but if you have any others or you run into other problems, please throw them down into the comments section below and we will get back at you ASAP.


newsletter icon

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 многим кажется простым и понятным. Однако, даже при написании самого простого кода, могут возникать ошибки во время выполнения — 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 требует тщательного анализа и отладки кода. Важно проверять типы данных, обрабатывать исключения, проверять входные данные, документировать код, использовать отладчик и перепроверять логику программы. Соблюдение этих рекомендаций поможет предотвратить многие ошибки времени выполнения и улучшит качество вашего кода.

Image of Python RuntimeError (Examples & Use Cases) | Initial Commit

Table of Contents

  • Introduction
  • What is a Runtimeerror error?
  • What causes run time error message in Python?
  • How do you handle a runtime error?
  • What is runtime error message example?
  • Zero Division Error raised
  • Index Error
  • How do I fix a built-in exception value error in Python?
  • What causes the built-in exception overflow error?
  • Summary
  • Next steps
  • References

Introduction

There are several types of errors in Python that help you debug your program. When you run your program, Python first checks for any syntax errors, and then runs the program. Errors thrown during syntax checking are called syntax errors. Errors that are thrown once the code is run are under the class of runtime errors. These errors will always include an error message printed to the interpreter. In this tutorial, you will learn several different types of runtime errors in python, what their error messages are, and how to fix them.

What is a Runtimeerror error?

A python run-time error is a class of python built-in exceptions that are thrown at run-time. There are many different types of run-time errors, we will cover them in this article. Some examples include type errors and name errors. run-time attribute errors fall under a larger group of concrete built-in exceptions in Python.

What causes run time error message in Python?

There are many things that can raise a runtime errors in python depending on the type of error that is thrown. Some questions you can ask yourself to debug including, are you:

  • dividing by zero?
  • using incorrect types in operations?
  • indexing past the length of a list?
  • accessing a key in dictionary that doesn’t exist?
  • using variables that haven’t been defined yet?
  • trying to import or access a file that does not exist?

If you checked for all of these things and you are still getting an error, then it may be caused by something else. We will cover some examples of causes and fixes of certain errors in the following sections.

How do you handle a runtime error?

How you handle a run-time error in python depends on the specific error that was thrown. Once way to generally handle run-time errors is by using a try/except block. You include the code that may cause a runtime error in the try clause. You can then specify how you want to handle the code in the case of an error in the except clause. Here is an example:

>>> y = 12
>>> x = 0
>>> try:
... z = y / x
>>> except:
...print("An error occurred")
...z = 0

This way you are alerted of the error without causing a raised exception and stopping your program.

What is runtime error message example?

Every run-time error in python prints a message to the interpreter indicating what caused raised error and what line it was on. Let’s take a look at some examples of common run-time errors and how to fix them.

Zero Division Error raised

A ZeroDivisionError is thrown when you try to divide or modulo by zero in your code, for example:

>>> x = 0
>>> y = 2
>>> if y % x == 0:
... print(y, :is divisible by", x)
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
ZeroDivisionError: integer division or modulo by zero

Note that the error message idicates the error is happening on line 3. We can avoid this by adding a check to make sure the number we’re modding by isn’t 0 before we perform the operation:

>>> x = 0
>>> y = 2
>>> if (x != 0) and (y % x == 0):
... print(y, "is divisible by", x)

Type Error

A TypeError is thrown when you try to perform an operation with incorrect types. For example, if you tried to concatenate an int and a string, you get a type error:

>>> x = "1"
>>> y = 2
>>> z = x + y
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'

The error will also specify which operation is throwing the error and what types you’re trying to use. In this case we can resolve this error by casting all the variables to integers to make sure we are only adding integers:

>>> x = "1"
>>> y = 2
>>> z = int(x) + int(y)
>>> print(x+y)
3

Another common cause for type errors is attempting to loop through an incorrect type. For example, attempting to iterate through an integer:

>>> for i in 10:
... print(i)
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
TypeError: 'int' object is not iterable

In this case the error tells us that we are attempting to iterate through an integer on line 3, which is not a type we can iterate through. Instead we want to use a for-range loop:

>>> for i in range(10):
... print(i)
0
1

One example of a library function that can throw a type error is the pandas.head() method from the Pandas library. The head function throws a type error if you provide an argument that is not an integer:

>>>df.head(2.5)
TypeError: cannot do positional indexing on RangeIndex with these indexers [2.5] of type float

You can learn more about the pandas head function here.

Key Error

A KeyError is thrown when you are trying to access a key in a dictionary that doesn’t exist. For example:

>>> d = {1: ["a"], 2: ["b"]}
>>> print(d[3])
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
KeyError: 3

The error will specify which key you are trying to access that does not exist. You can fix this by making sure to check if the key is in the dictionary before trying to access that specific key. You can check if a key exists in a dictionary by using the in function, which returns a boolean:

>>> d = {1: ["a"], 2: ["b"]}
>>> if 3 in d:
... print(d[3])

Index Error

An index error is caused by indexing into a list with an out of bounds index:

>>> L = [1,2,3]
>>> for i in range(10):
... print(L[i])

We can fix this by either adjusting the for loop to only loop over the range of the list, or adding a check before we index into the list to make sure the index is in range:

>>> L = [1,2,3]
>>> for i in range(len(L)):
... print(L[i])

or

>>> L = [1,2,3]
>>> for i in range(10):
... if i < len(L):
... print(L[i])

Name Error

A NameError is thrown when you try to use a variable that is not defined yet in the file. For example:

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

You can fix this by defining the variable on a line before the line it is called on:

>>>x = 5
>>>print(x)
5

Name errors can also be thrown if you try to use a variable that is already defined but out of scope. For example, if you try to use a local variable defined inside of a function globally:

>>>def foo(x,y):
             print(x + y)
>>>
>>>print(x)
Traceback (most recent call last):
  File "<string>", line 4, in <module>
NameError: name 'x' is not defined

To fix this, make sure you are only trying to access variables that are within scope.

File not found error

A FileNotFoundError is thrown when you try to access a file that does not exist in the directory you specified:

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

There are a couple ways to resolve the error. First you should check to make sure that the file you are trying to access is in your current directory. If not, make sure to specify the full filepath when trying to access that file, for example:

>>> open("/C:/folder1/folder2/file", "r")

How do I fix a built-in exception value error in Python?

A value error is caused by giving a function an input that is of the correct type, but an incorrect value. For example:

>>>import math
>>>math.sqrt(-100)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: math domain error

Here we get an error because the math.sqrt function only works with positive integers or zero as input. We can prevent this error by making sure that anything passed into the function is greater than or equal to zero.

What causes the built-in exception overflow error?

An overflow error is caused by an arithmetic operation that is too large for Python to represent.

For example:

>>>math.exp(5000)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: math range error

You can prevent overflow errors by making sure that the numbers you pass into functions are not too large.

Summary

In this tutorial, you learned that run-time errors are, when they occur in your program, and several ways to fix them. First, you learned that run-time errors are a type of built-in exceptions thrown at run-time. Next, you learned some common causes of run-time errors like dividing by zero and using incorrect types in operations. Then, you learned how to generally handle run-time errors using a try-except block. Last, you looked at several examples of things that can raise run-time errors and how to resolve them, including some less common errors like overflow errors and value errors.

Next steps

If you’re interested in learning more about the basics of Python, coding, and software development, check out our Coding Essentials Guidebook for Developers, where we cover the essential languages, concepts, and tools that you’ll need to become a professional developer.

Thanks and happy coding! We hope you enjoyed this article. If you have any questions or comments, feel free to reach out to jacob@initialcommit.io.

References

  1. Concrete Exceptions
  2. Built-in Exceptions

Final Notes

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

Содержание

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

    • 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 ошибка str object is not callable
  • Qsp ошибка 119
  • Python ошибка runtime error
  • Python ошибка killed
  • Qsp код ошибки 120