Это продолжение Обработать исключение, созданное в генераторе, и обсуждает более общую проблему.
У меня есть функция, которая читает данные в разных форматах. Все форматы ориентированы на линию или запись, а для каждого формата имеется специальная функция синтаксического анализа, реализованная в качестве генератора. Таким образом, основная функция чтения получает вход и генератор, который считывает соответствующий формат со входа и возвращает записи к основной функции:
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 - очень умный и проницательный материал.