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

Появление ошибок в процессе написания программы это неизбежный процесс в программировании.

Почему?

  1. Сложные задачи:
    • Программа — достаточно сложная вещь. Учесть все нюансы попросту невозможно
  2. Люди ошибаются:
    • Представьте, что программа — это ваш рецепт на кухне. Вы пишете шаги, но иногда наливаете соль вместо сахара. Точно так же программисты могут написать что-то неправильно из-за опечаток или неверного понимания.
  3. Различные платформы и среды выполнения:
    • Программа может работать на разных компьютерах, как игра на разных площадках. Иногда то, что работает на одной, может вызывать проблемы на другой из-за различий в правилах.
  4. Постоянно что-то меняется:
    • Мир постоянно меняется. В процессе изменений, что-то перестает работать. И в программировании — когда вы что-то меняете или добавляете, иногда появляются новые ошибки.
  5. Неожиданные гости:
    • Как если бы вам принесли странные или просроченные продукты для вашего рецепта. В программировании, если данные не такие, как ожидалось, это может вызвать проблемы.

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

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

Пример 1: Деление на ноль

Без обработки ошибок:

def divide_numbers(a, b):
    result = a / b
    return result

# Пример использования
result = divide_numbers(10, 0)
print(result)

Результат без обработки ошибок: Программа выдаст ошибку «ZeroDivisionError», и выполнение программы остановится. Результат не будет выведен.

С обработкой ошибок:

def divide_numbers(a, b):
    try:
        result = a / b
        return result
    except ZeroDivisionError:
        print("Ошибка: Деление на ноль невозможно!")

# Пример использования
result = divide_numbers(10, 0)
if result is not None:
    print(result)

Результат с обработкой ошибок: Программа выведет сообщение «Ошибка: Деление на ноль невозможно!» и продолжит выполнение. Результат не будет выведен.

Пример 2: Открытие файла

Без обработки ошибок:

file_path = "несуществующий_файл.txt"
file = open(file_path, 'r')
content = file.read()
print(content)

Результат без обработки ошибок: Программа выдаст ошибку «FileNotFoundError», и выполнение программы остановится. Результат не будет выведен.

С обработкой ошибок:

file_path = "несуществующий_файл.txt"

try:
    file = open(file_path, 'r')
    content = file.read()
    print(content)
except FileNotFoundError:
    print(f"Ошибка: Файл '{file_path}' не найден!")
except Exception as e:
    print(f"Произошла ошибка: {e}")
finally:
    if 'file' in locals() and file is not None:
        file.close()

Результат с обработкой ошибок: Программа выведет сообщение «Ошибка: Файл ‘несуществующий_файл.txt’ не найден!» и продолжит выполнение. Результат не будет выведен. В блоке finally, программа попытается закрыть файл, но так как файла нет, это также может вызвать ошибку.

Почему важно обрабатывать ошибки:

  1. Предотвращение краха программы:
    • Без обработки ошибок, если что-то идет не так, программа может просто «упасть» с ошибкой, оставив пользователя в недоумении. Обработка ошибок позволяет программе корректно завершить выполнение или предоставить информацию о проблеме.
  2. Более информативные сообщения:
    • Обработка ошибок позволяет предоставить пользователям более дружелюбные и информативные сообщения об ошибках, которые помогут им понять проблему и даже предпринять шаги для ее решения.
  3. Предотвращение нежелательных последствий:
    • В приведенных примерах обработка ошибок позволяет избежать деления на ноль или попыток открытия несуществующих файлов, что может привести к непредсказуемым и нежелательным последствиям.
  4. Управление ресурсами:
    • Обработка ошибок также позволяет корректно управлять ресурсами, такими как файлы. В примере с файлом, блок finally гарантирует, что файл будет закрыт, даже если произошла ошибка.

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

Типы ошибок в Python

В Python существует два основных типа ошибок: синтаксические ошибки и исключения (runtime errors).

  1. Синтаксические ошибки:
    • Эти ошибки происходят, когда нарушена правильная структура языка программирования. Например, это может быть неправильное использование ключевых слов, отсутствие двоеточия в конструкциях, ошибка в синтаксисе операторов и т.д.
    • Пример синтаксической ошибки:
      print("Hello World"
      
  2. Исключения (runtime errors):
    • Эти ошибки возникают во время выполнения программы, когда что-то идет не так в процессе выполнения кода. Например, деление на ноль, попытка доступа к несуществующему индексу в списке, открытие файла, который не существует, и т.д.
    • Пример исключения:
      x = 10 / 0
      

    Некоторые распространенные типы исключений в Python:

    • ZeroDivisionError: Возникает при попытке деления на ноль.
    • FileNotFoundError: Возникает, когда программа пытается открыть файл, который не существует.
    • IndexError: Возникает, когда происходит обращение к индексу, выходящему за пределы диапазона.
    • TypeError: Возникает, когда операция применяется к объекту несоответствующего типа данных.

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

Блок try-except

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

Общий синтаксис блока try-except:

try:
    # Код, который может вызвать исключение
    # ...
except ИмяИсключения as переменная:
    # Код, который выполняется в случае исключения
    # ...
  • ИмяИсключения: Это тип ожидаемого исключения. Может быть одним или несколькими типами исключений.
  • переменная: Это переменная, в которой будет храниться информация об исключении, если оно произойдет.

Примеры использования для обработки исключений:

  1. Деление на ноль:
    try:
        result = 10 / 0
    except ZeroDivisionError as e:
        print(f"Ошибка: {e}")
    
  2. Преобразование строки в число:
    user_input = input("Введите число: ")
    
    try:
        number = int(user_input)
        print(f"Вы ввели число: {number}")
    except ValueError as e:
        print(f"Ошибка: {e}. Введите корректное число.")
    
  3. Чтение файла:
    file_path = "несуществующий_файл.txt"
    
    try:
        with open(file_path, 'r') as file:
            content = file.read()
        print(content)
    except FileNotFoundError as e:
        print(f"Ошибка: {e}. Файл '{file_path}' не найден.")
    except Exception as e:
        print(f"Произошла ошибка: {e}")
    

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

Множественные блоки except

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

try:
    # Код, который может вызвать исключение
    # ...
except ТипИсключения1 as переменная1:
    # Код для обработки исключения ТипИсключения1
    # ...
except ТипИсключения2 as переменная2:
    # Код для обработки исключения ТипИсключения2
    # ...
# ...
except ОбщийТипИсключения as переменная:
    # Код для обработки всех остальных исключений
    # ...
  • ТипИсключения1, ТипИсключения2, …: Различные типы исключений, которые вы хотите обработать.
  • переменная1, переменная2, …: Переменные, в которых будет храниться информация об исключении.

Пример использования множественных блоков except:

user_input = input("Введите число или строку: ")

try:
    result = int(user_input)
    print(f"Вы ввели число: {result}")
except ValueError as ve:
    print(f"Ошибка преобразования в число: {ve}")
except TypeError as te:
    print(f"Ошибка типа данных: {te}")
except Exception as e:
    print(f"Произошла ошибка: {e}")

В этом примере используются три разных блока except:

  1. except ValueError: Обрабатывает ситуацию, когда введенные данные не могут быть преобразованы в число из-за ошибки значения.
  2. except TypeError: Обрабатывает ситуацию, когда в коде возникает ошибка типа данных.
  3. except Exception: Этот блок обрабатывает все остальные исключения, которые не были обработаны предыдущими блоками.

try-except-else

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

try:
    # Код, который может вызвать исключение
    # ...
except ТипИсключения as переменная:
    # Код для обработки исключения
    # ...
else:
    # Код, который выполняется, если в блоке try не произошло исключение
    # ...

Пример использования блока else:

try:
    user_input = int(input("Введите число: "))
except ValueError as ve:
    print(f"Ошибка: {ve}")
else:
    print("Вы ввели число успешно!")

В этом примере, если пользователь введет нечисловое значение и возникнет ValueError, программа перейдет к блоку except и выведет сообщение об ошибке. Если же пользователь введет число успешно, программа выполнит код в блоке else и выведет сообщение «Вы ввели число успешно!».

Другой пример с использованием блока else в работе с файлами:

file_path = "example.txt"

try:
    with open(file_path, 'r') as file:
        content = file.read()
except FileNotFoundError as fe:
    print(f"Ошибка: {fe}. Файл '{file_path}' не найден.")
else:
    print(f"Содержимое файла:\n{content}")

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

Блок finally

Блок finally в конструкции try-except предназначен для выполнения кода независимо от того, произошло исключение или нет. Код в блоке finally будет выполнен в любом случае. Общий синтаксис выглядит так:

try:
    # Код, который может вызвать исключение
    # ...
except ТипИсключения as переменная:
    # Код для обработки исключения
    # ...
finally:
    # Код, который выполнится независимо от того, произошло исключение или нет
    # ...

Пример использования блока finally:

try:
    file = open("example.txt", "r")
    content = file.read()
    # Предположим, здесь может произойти исключение
except FileNotFoundError as e:
    print(f"Ошибка: {e}. Файл не найден.")
else:
    print(f"Содержимое файла:\n{content}")
finally:
    if 'file' in locals() and file is not None:
        file.close()
        print("Файл был закрыт независимо от исключения.")

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

Освобождение ресурсов:

Одним из основных применений блока finally является освобождение ресурсов, таких как закрытие файлов, соединений с базой данных или сетевых соединений. Например:

try:
    db_connection = open_database_connection()
    # Работа с базой данных
except DatabaseError as e:
    print(f"Ошибка базы данных: {e}")
finally:
    if 'db_connection' in locals() and db_connection is not None:
        close_database_connection(db_connection)

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

Задания для тренировки

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

Задание 2. Создайте функцию, которая принимает два аргумента и возвращает результат деления первого на второе. Обработайте ошибку ZeroDivisionError, если второй аргумент равен нулю.

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

Задание 4. Создайте список чисел и попытайтесь получить элемент по индексу, который выходит за пределы списка. Обработайте ошибку IndexError.

Задание 5. Напишите функцию, которая принимает на вход строку и индекс, затем возвращает символ строки по указанному индексу. Обработайте ошибку IndexError, если индекс выходит за пределы длины строки.

Задание 6. Создайте словарь и попытайтесь получить значение по ключу, который отсутствует в словаре. Обработайте ошибку KeyError.

Задание 7. Напишите программу, которая просит пользователя ввести два числа и выполняет операцию деления на первое число второго числа. Обработайте ошибки ValueError (ввод нечисловых данных) и ZeroDivisionError (деление на ноль).

Задание 8. Создайте функцию, которая принимает на вход строку и пытается преобразовать ее в целое число. Обработайте ошибку ValueError и верните сообщение «Невозможно преобразовать в число».

Задание 9. Напишите программу, которая открывает файл, записывает в него текст и закрывает файл. Обработайте ошибку PermissionError, если у вас нет прав на запись в указанный файл.

Задание 10. Создайте класс Person с атрибутом возраста. Напишите метод, который возвращает сообщение вида «Возраст: [возраст] лет». Обработайте ошибку AttributeError, если атрибут «возраст» не существует.

Решения
# Решения с объяснением кода в комментариях:

# Задание 1.
try:
    user_input = int(input("Введите число: "))
except ValueError as ve:
    print(f"Ошибка: {ve}. Введены нечисловые данные.")

# Задание 2.
def divide(a, b):
    try:
        result = a / b
        return result
    except ZeroDivisionError as ze:
        print(f"Ошибка деления на ноль: {ze}")

# Задание 3.
try:
    with open("example.txt", "r") as file:
        content = file.read()
    print(f"Содержимое файла:\n{content}")
except FileNotFoundError as fe:
    print(f"Ошибка: {fe}. Файл не найден.")

# Задание 4.
numbers = [1, 2, 3]
try:
    value = numbers[5]
except IndexError as ie:
    print(f"Ошибка индекса: {ie}")

# Задание 5.
def get_char_by_index(s, index):
    try:
        char = s[index]
        return char
    except IndexError as ie:
        print(f"Ошибка индекса: {ie}")

# Задание 6.
my_dict = {'key': 'value'}
try:
    value = my_dict['nonexistent_key']
except KeyError as ke:
    print(f"Ошибка ключа: {ke}")

# Задание 7.
try:
    num1 = int(input("Введите первое число: "))
    num2 = int(input("Введите второе число: "))
    result = num2 / num1
    print(f"Результат деления: {result}")
except ValueError as ve:
    print(f"Ошибка: {ve}. Введены нечисловые данные.")
except ZeroDivisionError as ze:
    print(f"Ошибка деления на ноль: {ze}")

# Задание 8.
def convert_to_int(s):
    try:
        num = int(s)
        return num
    except ValueError:
        return "Невозможно преобразовать в число"

# Задание 9.
try:
    with open("example.txt", "w") as file:
        file.write("Hello, World!")
except PermissionError as pe:
    print(f"Ошибка доступа: {pe}. Нет прав на запись в файл.")

# Задание 10.
class Person:
    def __init__(self, age):
        self.age = age

    def get_age_message(self):
        try:
            return f"Возраст: {self.age} лет"
        except AttributeError:
            return "Ошибка: отсутствует атрибут 'возраст'"

# Пример использования для Задания 10:
person1 = Person(25)
print(person1.get_age_message())

Генерация собственных исключений. raise

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

Общий синтаксис:

raise ИмяИсключения("Сообщение об ошибке")
  • ИмяИсключения: Тип исключения, которое вы хотите сгенерировать.
  • "Сообщение об ошибке": Дополнительное сообщение, которое может быть передано при генерации исключения. Это необязательная часть.

Примеры:

  1. Генерация базового исключения:
    raise ValueError("Это мое исключение")
    
  2. Генерация собственного исключения:
    class MyCustomError(Exception):
        pass
    
    raise MyCustomError("Сообщение об ошибке")
    
  3. Генерация исключения с аргументами:
    class CustomErrorWithArgs(Exception):
        def __init__(self, arg1, arg2):
            self.arg1 = arg1
            self.arg2 = arg2
            super().__init__(f"Ошибка: {arg1}, {arg2}")
    
    raise CustomErrorWithArgs("Аргумент 1", "Аргумент 2")
    

Использование генерации исключений:

  • В функциях и методах: Вы можете использовать raise для генерации исключений внутри функций или методов в ответ на определенные условия или ошибки.
    def divide_numbers(a, b):
        if b == 0:
            raise ValueError("Деление на ноль невозможно")
        return a / b
    
  • В блоке try-except: Вы также можете использовать raise в блоках except для перегенерации (повторной генерации) исключения после его обработки.
    try:
        # код, который может вызвать исключение
    except SomeException as e:
        # обработка исключения
        raise AnotherException("Новое сообщение об ошибке") from e
    

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

Создание собственных исключений

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

Создание пользовательского исключения:

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

Пример создания пользовательского исключения:

class CustomError(Exception):
    def __init__(self, message="Пользовательская ошибка"):
        self.message = message
        super().__init__(self.message)

Пример использования пользовательского исключения:

def divide_numbers(a, b):
    if b == 0:
        raise CustomError("Деление на ноль невозможно")
    return a / b

try:
    result = divide_numbers(10, 0)
    print(result)
except CustomError as ce:
    print(f"Произошла ошибка: {ce}")

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

Задания на закрепление

Задание 11. Напишите программу, которая просит пользователя ввести число, генерирует исключение ValueError, если введенное число меньше нуля, и обрабатывает это исключение, выводя сообщение «Отрицательные числа не допускаются».

Задание 12. Создайте функцию, которая принимает два аргумента и генерирует исключение TypeError, если хотя бы один из них не является числом. Обработайте исключение, выведя сообщение «Аргументы должны быть числами».

Задание 13. Напишите программу, которая открывает файл для записи и генерирует исключение PermissionError, если у пользователя нет прав на запись в указанный файл. Обработайте исключение, выводя сообщение «Недостаточно прав для записи в файл».

Задание 14. Создайте класс TemperatureConverter, который принимает температуру в градусах Цельсия и генерирует исключение ValueError, если значение температуры ниже абсолютного нуля (-273.15°C). Обработайте исключение, выводя сообщение «Температура не может быть ниже абсолютного нуля».

Задание 15. Напишите программу, которая принимает от пользователя строку, генерирует исключение ValueError, если строка содержит не менее 10 символов, и обрабатывает исключение, выводя сообщение «Строка должна содержать менее 10 символов».

Решение
# Решения с объяснением кода в комментариях:

# Задание 11.
try:
    user_input = int(input("Введите число: "))
    if user_input < 0:
        raise ValueError("Введено отрицательное число")
except ValueError as ve:
    print(f"Ошибка: {ve}. Отрицательные числа не допускаются.")

# Задание 12.
def add_numbers(a, b):
    try:
        if not (isinstance(a, (int, float)) and isinstance(b, (int, float))):
            raise TypeError("Аргументы должны быть числами")
        result = a + b
        return result
    except TypeError as te:
        print(f"Ошибка: {te}")

# Задание 13.
try:
    with open("example.txt", "w") as file:
        file.write("Пример записи в файл")
except PermissionError as pe:
    print(f"Ошибка: {pe}. Недостаточно прав для записи в файл.")

# Задание 14.
class TemperatureConverter:
    def __init__(self, celsius):
        if celsius < -273.15:
            raise ValueError("Температура не может быть ниже абсолютного нуля")
        self.celsius = celsius

# Пример использования для Задания 14:
try:
    temp_converter = TemperatureConverter(-300)
except ValueError as ve:
    print(f"Ошибка: {ve}")

# Задание 15.
try:
    user_string = input("Введите строку (менее 10 символов): ")
    if len(user_string) >= 10:
        raise ValueError("Строка должна содержать менее 10 символов")
except ValueError as ve:
    print(f"Ошибка: {ve}. Строка должна содержать менее 10 символов.")

Практические рекомендации при обработке исключений

  1. Используйте конкретные типы исключений: Избегайте обработки всех исключений (Exception), так как это может скрыть реальные проблемы в коде. Используйте конкретные типы исключений, чтобы точно указать, какие ошибки вы ожидаете и обрабатываете.
    #Плохой код:
    try:
        result = 10 / 0
    except Exception as e:
        print(f"Произошла ошибка: {e}")
    
    #Хороший код:
    try:
        result = 10 / 0
    except ZeroDivisionError as zde:
        print(f"Ошибка деления на ноль: {zde}")
    except Exception as e:
        print(f"Произошла ошибка: {e}")
    
  2. Не подавляйте исключения без необходимости: Избегайте использования пустых блоков except без объяснения. Это может привести к трудностям в отладке кода, так как ошибки будут скрыты.
    
    #Плохой код:
    try:
        file = open("example.txt", "r")
        content = file.read()
        print(f"Содержимое файла:\n{content}")
    except FileNotFoundError as fe:
        pass
    
    
    #Хороший код:
    try:
        with open("example.txt", "r") as file:
            content = file.read()
    except FileNotFoundError as fe:
        print(f"Ошибка: {fe}. Файл не найден.")
    else:
        print(f"Содержимое файла:\n{content}")
    
  3. Обрабатывайте исключения по мере необходимости: Обрабатывайте исключения только там, где это действительно необходимо. Не обрабатывайте исключения в местах, где это может затруднить отладку или скрыть проблемы.
  4. Предоставляйте информативные сообщения об ошибках: Старайтесь предоставить пользователю или разработчику максимально информативное сообщение об ошибке. Это помогает быстро понять причину проблемы.
    #Плохой код:
    try:
        result = 10 / 0
    except ZeroDivisionError as zde:
        print(f"Произошла ошибка: {zde}")
    
    #Хороший код:
    try:
        result = 10 / 0
    except ZeroDivisionError as zde:
        print(f"Ошибка деления на ноль: {zde}")
    
  5. Используйте блок finally для освобождения ресурсов: Если ваш код выполняет какие-то действия, требующие освобождения ресурсов (например, закрытие файлов или соединений), используйте блок finally  или контекстный менеджер для этого.
    #Плохой код:
    file = open("example.txt", "r")
    try:
        content = file.read()
        # обработка содержимого файла
        file.close()
    except FileNotFoundError as fe:
        print(f"Ошибка: {fe}. Файл не найден.")
    
    #Хороший код:
    try:
        with open("example.txt", "r") as file:
            content = file.read()
        # обработка содержимого файла
    except FileNotFoundError as fe:
        print(f"Ошибка: {fe}. Файл не найден.")
    
  6. Используйте логирование для отслеживания ошибок: Логирование помогает отслеживать ошибки и их причины, даже если они не сразу видны пользователю. Используйте библиотеку logging для эффективного ведения журнала.
    #Плохой код:
    try:
        result = 10 / 0
    except ZeroDivisionError as zde:
        print(f"Ошибка деления на ноль: {zde}")
        # Логирование ошибки вручную
        log_file = open("error_log.txt", "a")
        log_file.write(f"Ошибка деления на ноль: {zde}\n")
        log_file.close()
    
    #Хороший код:
    import logging
    
    logging.basicConfig(filename='error_log.txt', level=logging.ERROR)
    
    try:
        result = 10 / 0
    except ZeroDivisionError as zde:
        logging.error(f"Ошибка деления на ноль: {zde}")
    
  7. Поднимайте исключения только там, где это имеет смысл: Не поднимайте исключения в тех местах, где их обработка нецелесообразна. Давайте ошибкам восходить к вызывающему коду, где они могут быть более адекватно обработаны.
  8. Документируйте ожидаемые исключения: Если ваш код предполагает возникновение определенных исключений, документируйте это, чтобы другие разработчики знали, какие ошибки ожидать и как с ними обращаться.

Проектные работы, где необходима обработка исключений

  1. Проверка ошибок HTTP-запроса в веб-скрапинге с использованием requests.raise_for_status() для корректной обработки ошибок запроса.

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

  1. Обработка ошибок JSON-парсинга при работе с API, а также логирование ошибок для последующего анализа.

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

  1. Транзакционная обработка ошибок в базе данных, включая откат транзакции в случае возникновения исключения.
Понравилась статья? Поделиться с друзьями:
Школа Виктора Комлева
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!:

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.