Нахождение номера строки, где происходит исключение в коде Python - PullRequest
10 голосов
/ 05 августа 2011

У меня есть код, подобный следующему:

try:
  if x:
      statement1
      statement2
      statement3
  elif y:
      statement4
      statement5
      statement6
  else:
      raise

except:
      statement7

Здесь я уверен, что исключение происходит в блоке If x:, но я хотел бы знать, в каком операторе If x: блокируетсяисключение происходит.Есть ли способ получить номер строки, где происходит исключение?

С уважением,

Ответы [ 9 ]

21 голосов
/ 05 августа 2011

что по этому поводу:

try:
  if x:
      print 'before statement 1'
      statement1
      print 'before statement 2' #ecc. ecc.
      statement2
      statement3
  elif y:
      statement4
      statement5
      statement6
  else:
      raise

except:
      statement7

это простой обходной путь, но я предлагаю использовать отладчик

или даже лучше, используйте модуль sys: D

try:
      if x:
          print 'before statement 1'
          statement1
          print 'before statement 2' #ecc. ecc.
          statement2
          statement3
      elif y:
          statement4
          statement5
          statement6
      else:
          raise
except:
    print sys.exc_traceback.tb_lineno 
    #this is the line number, but there are also other infos
13 голосов
/ 05 августа 2011

Я полагаю, что несколько ответов здесь, рекомендующих вам более тщательно управлять своими try/except блоками, - это ответ, который вы ищете. Это стиль, а не библиотека.

Однако иногда мы оказываемся в ситуации, когда это не стиль, и вам действительно нужно нужен номер строки, чтобы выполнить какое-то другое программирующее действие. Если это то, что вы спрашиваете, вы должны рассмотреть модуль traceback. Вы можете извлечь всю необходимую вам информацию о самом последнем исключении. Функция tb_lineno вернет номер строки, вызвавшей исключение.

>>> import traceback
>>> dir(traceback)
['__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '_format_final_exc_line', '_print', '_some_str', 'extract_stack', 'extract_tb', 'format_exc', 'format_exception', 'format_exception_only', 'format_list', 'format_stack', 'format_tb', 'linecache', 'print_exc', 'print_exception', 'print_last', 'print_list', 'print_stack', 'print_tb', 'sys', 'tb_lineno', 'types']
>>> help(traceback.tb_lineno)
Help on function tb_lineno in module traceback:

tb_lineno(tb)
Calculate correct line number of traceback given in tb.
Obsolete in 2.3

Более новые версии трассировки трассировки исправляют проблему до 2.3, позволяя приведенному ниже коду работать так, как было задумано: (это «правильный путь»)

import traceback
import sys

try:
    raise Exception("foo")
except:
    for frame in traceback.extract_tb(sys.exc_info()[2]):
        fname,lineno,fn,text = frame
        print "Error in %s on line %d" % (fname, lineno)
4 голосов
/ 01 июня 2012

Вы должны запустить вашу программу в отладчике, например pdb. Это позволит вам нормально выполнять код и затем проверять окружение, когда происходит что-то непредвиденное.

Учитывая скрипт с именем 'main.py', запустите его так:

python -m pdb main.py

Затем, когда ваша программа запускается, она запускается в отладчике. Введите c, чтобы продолжить до следующей точки останова (или сбоя). Затем вы можете изучить окружающую среду, выполнив такие действия, как print spam.eggs. Вы также можете установить точки останова, выполнив pdb.set_trace() (я обычно делаю import pdb; pdb.set_trace()).

Кроме того, что вы имеете в виду, что «утверждение 3» может вызвать исключение? Вы ожидаете исключения? Если это так, может быть лучше написать блок try / исключением вокруг этого оператора, чтобы программа могла продолжить.

3 голосов
/ 21 марта 2014

Основываясь на JJ выше ..

Преимущество использования системных ошибок перед операторами состоит в том, что они записывают более конкретную информацию, которая поможет отладке позже (поверьте, я получаю много)

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

Подробнее ... Traceback & Sys

import traceback
import sys

try:
    print 1/0

except Exception as e:
    print '1', e.__doc__
    print '2', sys.exc_info()
    print '3', sys.exc_info()[0]
    print '4', sys.exc_info()[1]
    print '5', sys.exc_info()[2], 'Sorry I mean line...',traceback.tb_lineno(sys.exc_info()[2])
    ex_type, ex, tb = sys.exc_info()
    print '6', traceback.print_tb(tb)

Выход

>  1  Second argument to a division or modulo operation was zero. 
>  2  (<type 'exceptions.ZeroDivisionError'>, ZeroDivisionError('integer division
>      or modulo by zero',), <traceback object at 0x022DCF30>) 
>  3  <type 'exceptions.ZeroDivisionError'> 
>  4  integer division or modulo by zero 
>  5  <traceback object at 0x022DCF30> Sorry I mean line... 5
>  6  File "Z:\Programming\Python 2.7\Error.py", line 5, in <module>
>     print 1/0 
      None
>>>
3 голосов
/ 31 января 2013

До этого я делал следующее:

try:
    doing = "statement1"
    statement1
    doing = "statement2"
    statement2
    doing = "statement3"
    statement3
    doing = "statement4"
    statement4

 except:
    print "exception occurred doing ", doing

Преимущество перед печатью контрольных точек в том, что нет журнала, если только на самом деле есть исключение.

2 голосов
/ 05 августа 2011

Если вы реструктурируете код следующим образом, вы должны получить номер строки при повторном возникновении исключения:

except:
    statement7
    raise
2 голосов
/ 05 августа 2011

Вы должны обернуть утверждения, которые вам небезразличны, более плотно.Извлечение номера строки из трассировки будет очень хрупким.

1 голос
/ 06 августа 2011

Использование общего оператора кроме - обычно плохая практика программирования, поэтому в своем операторе вы должны указать, какое исключение вы хотите перехватить.(например, кроме ValueError:)

Более того, вы должны окружить try, за исключением структуры, биты кода, которые должны вызывать исключение.

0 голосов
/ 05 августа 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...