Есть ли способ отменить инициализацию класса объекта, если в Python возникает ошибка?

class EntityRetrieval(object):
    
    def __init__(self,
                 entity_kb_path: str):
        
        """
        Args
            entity_kb_path: path of entity knowledge base (string) which is json format
        """
        
        try:        
            entity_kb = json.load(open(entity_kb_path,'r'))
        except Exception as e:
            logging.error(e)
            
        # Don't use entity type 
        entity_dict = {}
        
        for entity_type, entities in entity_kb.items():
            for entity_id, list_entity_strings in entities.items():
                entity_dict[entity_id] = list_entity_strings

Выше мой уродливый код. Вот что меня волнует:

  • Действительно ли нужно перехватывать ошибки, чтобы предотвратить сбой? В приведенном выше коде entity_kb_path должен быть файлом json. Возможно, произошла ошибка неправильного формата файла или ошибка «не найден файл». И я пытаюсь выдать сообщение об ошибке пользователю, когда он не передает правильный аргумент, вместо того, чтобы выдать сбой.
  • Но когда я использую try catch, инициализация все еще выполняется и возвращает экземпляр, я думаю, что это нелогично, я имею в виду, что инициализация должна прекратиться, верно?
  • Если попробовать, кроме помещает туда, то произойдет что-то странное: переменная entity_kb может не быть объявлена. Но код блока процесса, стоящий за этим, слишком длинный. Возможно, я не захочу помещать это в блок try.

Как же действовать в таких сценариях?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
58
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

import sys

try:        
    entity_kb = json.load(open(entity_kb_path,'r'))
except Exception as e:
    logging.error(e)
    sys.exit(1)

Основываясь на ответе @Thecave3, я думаю, raise делает sys.exit(1), верно?

jupyter 23.04.2024 07:55

Оператор raise сам по себе повторно вызовет/распространит исключение, которое в данный момент обрабатывается. А если нет другого обработчика исключений для обработки повторного исключения, программа завершится с кодом состояния 1, но также выполнит обратную трассировку. Поскольку вы упоминаете, что «я пытаюсь выдать сообщение об ошибке пользователю, когда он не передает правильный аргумент вместо того, чтобы выдать сбой», я считаю, что вы хотите избежать создания вывода трассировки (который выглядит как сбой) и вместо этого выводить ошибку через logging , и в этом случае вам следует явно выйти из программы, а не делать повторный рейз.

blhsing 23.04.2024 08:06

эй, это работает только в __main__? Я имею в виду .py. Когда я тестирую работу на ноутбуке, он все равно выдает сбой с довольно сложной ошибкой, например During handling of the above exception, another exception occurred

jupyter 23.04.2024 08:15

В любом случае спасибо за ваше удивительное понимание и объяснение.

jupyter 23.04.2024 08:16

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

blhsing 23.04.2024 08:36
Ответ принят как подходящий

Действительно ли нужно перехватывать ошибки, чтобы предотвратить сбой?

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

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

Пример кода вашего класса:

class EntityRetrieval(object):
    
    def __init__(self, entity_kb_path: str):
        
        try:        
            entity_kb = json.load(open(entity_kb_path,'r'))
        except Exception as e:
            logging.error(e)
            raise e # throw again the Exception e after logging

       # initialize the class as you prefer

 try:        
     test = EntityRetrieval('')
 except Exception as e:
        # test is not initialized here, i.e., test is None -> True
        test = EntityRetrieval('correct/path/file.json')
        # or whatever operation to handle the error
 
 # at this point test is not None anymore

Соответствующее изменение, которое я внес в ваш код, — это вызов raise e в случае ошибок, чтобы уведомить пользователя о том, что произошло. Второй try/catch — это пример, показывающий возможную модель ответа.

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

Пример для вашего случая:

class EntityRetrieval(object):
    
    def __init__(self, entity_kb_path: str):
        try:        
            self.entity_kb = json.load(open(entity_kb_path,'r'))
        except Exception as e:
            logging.error(e)
            raise e # throw again the Exception e after logging
    
    def operate_on_file(self):
       # Do here all your ops

 try:        
     test = EntityRetrieval('')
 except Exception as e:
        # test is not initialized here, i.e., test is None -> True
        test = EntityRetrieval('correct/path/file.json')
        # or whatever operation to handle the error
 
 # at this point test is not None anymore
 test.operate_on_file()

Другие вопросы по теме