Хочу поделиться своим соображением по поводу эксепшенов
тк. я не люблю читать книжки по кодингу, а если и читаю то все моментально забываю – некоторые приемы, давно описанные в книгах, ко мне приходят лишь с опытом, когда я начинаю понимать зачем это нужно и как мне поможет
с пхп я вообще не юзал эксепшены – просто не понимал зачем они нужны
с питоном ситуация изменилась
жирным я выделил те места в коде, на которые стоит обратить внимание
сначала я научился проверять наличие индекса у листа, т.к встроенных средств для этого в питоне нет:
try:
test = arr[5]
except:
print(’fail’)
потом я нашел универсальный способ узнать в чем ошибка:
try:
test = arr[5]
except Exception as ex:
print(’fail: ‘ + ex)
в это время я ещё узнал что строки в питоне неизменяемые и создается три строки в памяти: ‘fail: ‘, ex, ‘fail: ex’
поэтому начал везде применять проценты (хз как грамотно назвать):
try:
test = arr[5]
except Exception as ex:
print(’fail: %s’ % ex)
Но отсюда нельзя получить трейсбек – список вызовов функций, по которому можно определить где ошибка, поэтому делаем вот что:
import traceback
try:
test = arr[5]
except Exception as ex:
print(’fail: %s’ % ex)
print(traceback.print_exc(file=sys.stdout))
—————
Далее,
Я сделал функцию parse, для удобного выдирания регулярок:
def parse(pattern, data):
”’ возвращает первое совпадение pattern в data ”’
m = re.search(pattern, data)
if not m:
return ‘NOT FOUND’
return m.group(1)
Возвращать фразу Нот фаунд – идиотское решение.
Я стал мучаться с нерабочими запросами, куда вместо значения паттерна попадала эта фраза, например:
t = hlp.parse(r’регулярка’, page)
data = {
‘data’: t # и сюда мы получаем ‘NOT FOUND’, даже не зная о проблеме
}
Ещё хуже, когда из ответа к примеру бралось первое значение:
t = hlp.parse(r’регулярка’, page)
t[0] # F — такое было совсем недавно, полный ппц, долго ломал голову что за клятая F
Тогда стал проверять значение:
t = hlp.parse(r’регулярка’, page)
if t == ‘NOT FOUND’
Тут заметь что нельзя делать is вместо ==. Is возвращает true только для маленьких строк, что закешировались в памяти и имеют постоянный адрес. Большие строки и числа свой адрес меняют и is возвращает False
t = ‘abc’
t is ‘abc’ # True
t = 12312312312
t is 12312312312 # False
В общем, функция стала возвращать False:
def parse(pattern, data):
”’ возвращает первое совпадение pattern в data ”’
m = re.search(pattern, data)
if not m:
return False
return m.group(1)
Это удобно, код весь полнится проверками и работает стабильно:
numbr = hlp.parse(r’playa_link = \’http://promodj.ru/prelisten/\’ + ([0-9]+)’, page)
if numbr is False:
self.log(’не нашел numbr’, ‘!’, tid=tid)
Но недавно, Эл приехал в Новосиб и мы сидели на кухне, я ему рассказывал про эксепшены в питоне.
У меня в том же линкедине самое обычное дело:
path = hlp.parse(’SUCCESS”,”value”:”([^"]+)’, page)
if path is False:
self.log(’[#%d] не могу выдрать path’ % tid, ‘!’)
return
part = hlp.parse(’name=”addPosition” href=”([^"]+)’, page.replace(’\\”‘, ‘”‘))
if part is False:
self.log(’[#%d] не нашел ссылку на добавление компании акка’ % tid, ‘!’)
return False
uid = hlp.parse(r’LIM:([0-9]+)’, cookie)
if uid is False:
self.log(’[#%d] не нашел uid в куках’ % tid, ‘!’)
return False
Потом я правда упростил до такого:
csrf = hlp.parse(r’csrfToken” value=”([^"]+)’, page)
upld_info = hlp.parse(r’upload_info” type=”hidden” value=”([^"]*)’, page)
upldjs = hlp.parse(r’upload_info_with_js” type=”hidden” value=”([^"]*)’, page)
if False in [csrf, upld_info, upldjs]:
self.log(’[#%d] не нашли переменные csrf, upld_info, upldjs’ % tid, ‘!’)
return False
Но сейчас меня внезапно осенило.
Я ему сам сказал что можно все завернуть в один try-catch и это очень удобно, при том что сам делаю наоборот!
try:
csrf = hlp.parse(r’csrfToken” value=”([^"]+)’, page)
upld_info = hlp.parse(r’upload_info” type=”hidden” value=”([^"]*)’, page)
upldjs = hlp.parse(r’upload_info_with_js” type=”hidden” value=”([^"]*)’, page)
except Exception as ex:
print(‘parsing exception: %s’ % ex)
Надо лишь сделать чтобы все parse не возвращали False, а кидали эксепшен
raise Exception(”error parsing csrf”)
raise Exception(”error parsing upld_info”)
raise Exception(”error parsing upldjs”)
Хреново лишь то, что у меня все проекты заточены на False
менять на эксепшен – значит переписывать кучу кода
Сейчас я в раздумьях как сделать функцию универсальной, чтобы в новом коде она уже могла кидать эксепшен.