try, except через def. Не понятна логика
Учусь парсить. При парсинге не кажая страница содержит определённые строки. Отрабатываю исключение через try/except - получается. При добавлени обработки через def -не работает.
Выражение 1. Отрабатывает None строки отлично:
try:
saller_rate = "https://www.farpost.ru/" + soup.find("a", class_="ratingPositive").get("href")
except:
saller_rate = None
Выражение 2. Не отрабатывает и выдаёт ошибку.
def test(vir):
try:
rez=vir
except:
rez=None
return rez
saller_rate_link = test("https://www.farpost.ru/" + soup.find("a", class_="ratingPositive").get("href"))
Ошибка:
saller_rate_link = test("https://www.farpost.ru/" + soup.find("a", class_="ratingPositive").get("href")) # Ссылка на рейтинг продавца
AttributeError: 'NoneType' object has no attribute 'get'
Подскажите как правильно добавить обработку в функцию, т.к. стрко десятки и добавлять для каждую свою try/except сильно загромождает код.
Ответы (2 шт):
В функции test(vir) в блоке try вы просто присваиваете значение, оно никогда не перейдет к except. Эта конструкция здесь бессмысленна.
try-except нужно применять к данной конструкции soup.find("a", class_="ratingPositive").get("href") т.к. именно она возвращает None, если ничего не находит, а конкатенация строки и None в результате дает None.
Вот смотрите, вы написали вот так:
foo(очень + длинное + выражение)
Возможно, вы думаете что тем самым вы передаёте очень + длинное + выражение как параметр функции foo - но это не совсем так. На всех современных языках программирования общего назначения вы не можете передать в качестве параметра выражение, передаётся всегда только вычисленное значение.
А это означает, что если при вычислении очень + длинное + выражение произойдёт ошибка - функция foo не будет вызвана, и потому никак не сможет эту ошибку обработать.
Что тут можно сделать? Ну, если ваша цель - проигнорировать любые ошибки, то можно воспользоваться лямбда-функциями. Превратив ваше выражение в лямбду, вы сможете передать его в функцию целиком и вызвать уже внутри:
foo(lambda: очень + длинное + выражение)
Или, более конкретно:
def test(expr):
try:
return expr()
except:
return None
saller_rate_link = test(labmda: …)
Но я бы не рекомендовал вам так делать. Делая так, вы игнорируете любые ошибки возникающие при вычислении, и теряете информацию о том какая ошибка произошла. Однажды ваша программа, будучи запущенной в неожиданных условиях, просто выдаст на выходе None - и вас будут ожидать часы и дни попыток узнать что именно там произошло.
Ожидаемые ситуации следует обрабатывать не через try/except - а прописывая явные проверки на этот случай. К примеру, если вы пытаетесь отловить ситуацию, когда метод find вернул None - ну так и проверьте именно этот случай:
def get_saller_rate_link(soup):
if (ratingPositiveLink := soup.find("a", class_="ratingPositive")) is None:
return None
return … + ratingPositiveLink.get("href") + …
Если же подобная ситуация ожидаемой не является - имеет смысл ловить её через try/except, но делать это надо не индивидуально для каждой строчки - а для крупных блоков. И, главное, надо не "проглатывать" исключение, а выводить его в консоль или лог-файл:
import traceback
try:
saller_rate_link = …
another_link = …
some_data = …
another data = …
except Exception as e:
traceback.print_exception(e)