Что при обработке исключения может случиться другое исключение это как раз нормально. Ненормально, что всё это маскируется отлавливанием корневного класса Exception.
Плохая практика ловить любой Exception и даже не выводить его содержание с помощью хотя бы обычного print. Например, в недрах вызываемого кода ошибка из-за исчерпания места на диске, в обработчике вызываешь опять этот код и в недрах случается то же самое. Там вообще может случиться что угодно. Закончиться память в абсолютно любой строчке, например.
Также плохая практика генерировать абстрактный Exception на конкретную ошибку. Это может быть пригодно для набросанного для разового запуска скрипта, но в целом плохо, тем более это не сложно решается:
class NoTrainDataLoaded(Exception):
pass
...
raise NoTrainDataLoaded("Call your_model_object.load_train_data first!")
...
try:
...
except NoTrainDataLoaded:
logger.info("Train data not loaded yet, load default data...")
my_model.load_train_data("mimimi-cats-and-dogs")
continue
Если вдруг случится исключение, которое не упомянуто в except, то скрипт упадёт, и это хорошо. Пусть он не пытается делать какую попало реакцию на неясно какую ошибку.