2016-10-19 3 views
0

Я работаю над серией сценариев, которые извлекают URL-адреса из базы данных и использует textstat package для расчета читаемости страницы на основе набора предопределенных вычислений. Функция ниже берет url (из CouchDB), вычисляет определенные показатели удобочитаемости, а затем сохраняет оценки обратно в один и тот же документ CouchDB.Продолжить исключение в Python

Проблема, с которой я столкнулся, связана с обработкой ошибок. Например, для вычисления оценки Flesch Reading Ease требуется подсчет общего количества предложений на странице. Если это возвращается как ноль, генерируется исключение. Есть ли способ поймать это исключение, сохранить примечание об исключении в базе данных и перейти к следующему URL-адресу в списке? Могу ли я сделать это в функции ниже (предпочтительнее), или мне нужно будет отредактировать сам пакет?

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

def get_readability_data(db, url, doc_id, rank, index): 
    readability_data = {} 
    readability_data['url'] = url 
    readability_data['rank'] = rank 
    user_agent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)' 
    headers = { 'User-Agent' : user_agent } 
    try: 
     req = urllib.request.Request(url) 
     response = urllib.request.urlopen(req) 
     content = response.read() 
     readable_article = Document(content).summary() 
     soup = BeautifulSoup(readable_article, "lxml") 
     text = soup.body.get_text() 
     try: 
      readability_data['flesch_reading_ease'] = textstat.flesch_reading_ease(text) 
      readability_data['smog_index'] = textstat.smog_index(text) 
      readability_data['flesch_kincaid_grade'] = textstat.flesch_kincaid_grade(text) 
      readability_data['coleman_liau'] = textstat.coleman_liau_index(text) 
      readability_data['automated_readability_index'] = textstat.automated_readability_index(text) 
      readability_data['dale_chall_score'] = textstat.dale_chall_readability_score(text) 
      readability_data['linear_write_formula'] = textstat.linsear_write_formula(text) 
      readability_data['gunning_fog'] = textstat.gunning_fog(text) 
      readability_data['total_words'] = textstat.lexicon_count(text) 
      readability_data['difficult_words'] = textstat.difficult_words(text) 
      readability_data['syllables'] = textstat.syllable_count(text) 
      readability_data['sentences'] = textstat.sentence_count(text) 
      readability_data['readability_consensus'] = textstat.text_standard(text) 
      readability_data['readability_scores_date'] = time.strftime("%a %b %d %H:%M:%S %Y") 

      # use the doc_id to make sure we're saving this in the appropriate place 
      readability = json.dumps(readability_data, sort_keys=True, indent=4 * ' ') 
      doc = db.get(doc_id) 
      data = json.loads(readability) 
      doc['search_details']['search_details'][index]['readability'] = data 
      #print(doc['search_details']['search_details'][index]) 
      db.save(doc) 
      time.sleep(.5) 

     except: # catch *all* exceptions 
      e = sys.exc_info()[0] 
      write_to_page("<p>---ERROR---: %s</p>" % e) 

    except urllib.error.HTTPError as err: 
     print(err.code) 

Это ошибка я получаю:

Error(ASL): Sentence Count is Zero, Cannot Divide 
Error(ASyPW): Number of words are zero, cannot divide 
Traceback (most recent call last): 
    File "new_get_readability.py", line 114, in get_readability_data 
    readability_data['flesch_reading_ease'] = textstat.flesch_reading_ease(text) 
    File "/Users/jrs/anaconda/lib/python3.5/site-packages/textstat/textstat.py", line 118, in flesch_reading_ease 
    FRE = 206.835 - float(1.015 * ASL) - float(84.6 * ASW) 
TypeError: unsupported operand type(s) for *: 'float' and 'NoneType' 

Это код, который вызывает функцию:

if __name__ == '__main__': 
    db = connect_to_db(parse_args()) 
    print("~~~~~~~~~~" + " GETTING IDs " + "~~~~~~~~~~") 
    ids = get_ids(db) 
    for i in ids: 
     details = get_urls(db, i) 
     for d in details: 
      get_readability_data(db, d['url'], d['id'], d['rank'], d['index']) 
+0

Вы, очевидно, знаете, как использовать 'try' /' except', так что я с трудом проблем с пониманием того, что проблема есть. –

+1

проверить ASL и ASW, один из них может быть None – TurtleIzzy

+0

Спасибо, @MarkRansom. Я думал, что понял try/except тоже, но он не ведет себя так, как я ожидал бы (так что где-то есть пробел в знаниях). Это исключение выбрасывается одной из функций пакета textstat, поэтому я хочу знать, нужно ли мне самому отредактировать сам пакет, чтобы обойти его, или если есть другой вариант. – Ryan

ответ

0

Это, как правило, хорошая практика, чтобы держать try: except: блоки как можно , Я бы обернул ваши функции textstat в какой-то декоратор, который ловит ожидаемое вами исключение и возвращает выход функции и исключение.

, например:

def catchExceptions(exception): #decorator with args (sorta boilerplate) 
    def decorator(func): 
     def wrapper(*args, **kwargs): 
      try: 
       retval = func(*args, **kwargs) 
      except exception as e: 
       return None, e 
      else: 
       return retval, None 
     return wrapper 
    return decorator 

@catchExceptions(ZeroDivisionError) 
def testfunc(x): 
    return 11/x 

print testfunc(0) 
print '-----' 
print testfunc(3) 

печатает:

(None, ZeroDivisionError('integer division or modulo by zero',)) 
----- 
(3, None) 
Смежные вопросы