LSDEEX

September 10, 2011

Письмо про эксепшены (дабы не пропало)

Filed under: python — admin @ 1:28 pm

Хочу поделиться своим соображением по поводу эксепшенов

тк. я не люблю читать книжки по кодингу, а если и читаю то все моментально забываю – некоторые приемы, давно описанные в книгах, ко мне приходят лишь с опытом, когда я начинаю понимать зачем это нужно и как мне поможет

с пхп я вообще не юзал эксепшены – просто не понимал зачем они нужны
с питоном ситуация изменилась

жирным я выделил те места в коде, на которые стоит обратить внимание

сначала я научился проверять наличие индекса у листа, т.к встроенных средств для этого в питоне нет:

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
менять на эксепшен – значит переписывать кучу кода

Сейчас я в раздумьях как сделать функцию универсальной, чтобы в новом коде она уже могла кидать эксепшен.

No Comments

No comments yet.

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.

Powered by WordPress