Это продолжение Обработать исключение, созданное в генераторе, и обсуждает более общую проблему.
У меня есть функция, которая читает данные в разных форматах. Все форматы ориентированы на линию или запись, а для каждого формата имеется специальная функция синтаксического анализа, реализованная в качестве генератора. Таким образом, основная функция чтения получает вход и генератор, который считывает соответствующий формат со входа и возвращает записи к основной функции:
def read(stream, parsefunc):
for record in parsefunc(stream):
do_stuff(record)
где parsefunc что-то вроде:
def parsefunc(stream):
while not eof(stream):
rec = read_record(stream)
do some stuff
yield rec
Проблема, с которой я сталкиваюсь, заключается в том, что while parsefunc может генерировать исключение (например, при чтении из потока), он не знает, как с ним справиться. Функция, ответственная за обработку исключений, является основной функцией read. Обратите внимание, что исключения происходят на основе записи, поэтому, даже если одна запись выходит из строя, генератор должен продолжить свою работу и вернуть записи до тех пор, пока весь поток не будет исчерпан.
В предыдущем вопросе я попытался поместить next(parsefunc) в блок try, но, как оказалось, это не сработает. Поэтому я должен добавить try-except к самому parsefunc, а затем каким-то образом доставить исключения потребителю:
def parsefunc(stream):
while not eof(stream):
try:
rec = read_record()
yield rec
except Exception as e:
?????
Я довольно неохотно делаю это, потому что
- Нет смысла использовать
tryв функции, которая не предназначена для обработки каких-либо исключений. - Мне непонятно, как передавать исключения из функции потребления
- там будет много форматов и много
parsefunc, я не хочу загромождать их слишком большим вспомогательным кодом.
Есть ли предложения по лучшей архитектуре?
Заметка для гуглеров: в дополнение к верхнему ответу обратите внимание на senderle и сообщения Jon's - очень умный и проницательный материал.