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. Возможно, произошла ошибка неправильного формата файла или ошибка «не найден файл». И я пытаюсь выдать сообщение об ошибке пользователю, когда он не передает правильный аргумент, вместо того, чтобы выдать сбой.entity_kb
может не быть объявлена. Но код блока процесса, стоящий за этим, слишком длинный. Возможно, я не захочу помещать это в блок try
.Как же действовать в таких сценариях?
Вы можете сделать обработчик исключений выйти из программы с ненулевым кодом состояния после создания вывода журнала:
import sys
try:
entity_kb = json.load(open(entity_kb_path,'r'))
except Exception as e:
logging.error(e)
sys.exit(1)
Оператор raise
сам по себе повторно вызовет/распространит исключение, которое в данный момент обрабатывается. А если нет другого обработчика исключений для обработки повторного исключения, программа завершится с кодом состояния 1, но также выполнит обратную трассировку. Поскольку вы упоминаете, что «я пытаюсь выдать сообщение об ошибке пользователю, когда он не передает правильный аргумент вместо того, чтобы выдать сбой», я считаю, что вы хотите избежать создания вывода трассировки (который выглядит как сбой) и вместо этого выводить ошибку через logging
, и в этом случае вам следует явно выйти из программы, а не делать повторный рейз.
эй, это работает только в __main__
? Я имею в виду .py
. Когда я тестирую работу на ноутбуке, он все равно выдает сбой с довольно сложной ошибкой, например During handling of the above exception, another exception occurred
В любом случае спасибо за ваше удивительное понимание и объяснение.
Оно должно работать везде. Трудно сказать, как вы допускаете еще одну ошибку в своем обработчике исключений, не видя фактического кода.
Действительно ли нужно перехватывать ошибки, чтобы предотвратить сбой?
Если вы не обрабатываете исключение ни в одной части кода, код обязательно выйдет из строя.
Я думаю, вы можете позволить пользователю вашего класса (например, вам) решать, вызывать ли сбой кода или обрабатывать исключение по-другому, например, изменить путь.
Пример кода вашего класса:
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()
Основываясь на ответе @Thecave3, я думаю,
raise
делаетsys.exit(1)
, верно?