Поиск инструкции печати в Python
Иногда я оставляю отладочные заявления печати в своем проекте, и его трудно найти. Есть ли способ узнать, какая строка печатает что-то в частности?
Sidenote
Похоже, что поиск smart может решить большинство случаев. В Pydev (и других IDE) есть функция поиска, которая позволяет выполнять поиск по всем файлам в проекте. Конечно, аналогичный эффект можно получить с помощью grep с флагом -rn, хотя вы получаете только номера строк вместо прямых ссылок.
"print (" работает намного лучше в моем коде, и часто есть дополнительный текст в операторе печати, который можно искать с помощью регулярного выражения. Самый сложный случай - когда вы только что напечатали print (x), хотя это можно найти регулярное выражение, в котором значение внутри x не начинается или не заканчивается кавычками (спасибо! BecomingGuro)
Ответы
Ответ 1
Вы спрашивали о статических решениях. Здесь динамический. Предположим, вы запустили код и видите ошибочную печать или запись в файл sys.stdout и хотите знать, откуда она взялась. Вы можете заменить sys.stdout и позволить отслеживанию исключений помочь вам:
>>> import sys
>>> def go():
... sys.stdout = None
... print "Hello!"
...
>>> go()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in go
AttributeError: 'NoneType' object has no attribute 'write'
>>> print "Here"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'write'
>>>
Для чего-то более сложного, замените "sys.stdout" на то, что сообщает, где находится оператор печати. Я буду использовать traceback.print_stack(), чтобы показать полный стек, но вы можете делать другие вещи, например, используя sys._getframe() для поиска одного уровня стека, чтобы получить номер строки и имя файла.
import sys
import traceback
class TracePrints(object):
def __init__(self):
self.stdout = sys.stdout
def write(self, s):
self.stdout.write("Writing %r\n" % s)
traceback.print_stack(file=self.stdout)
sys.stdout = TracePrints()
def a():
print "I am here"
def b():
a()
b()
Здесь вывод
Writing 'I am here'
File "stdout.py", line 19, in <module>
b()
File "stdout.py", line 17, in b
a()
File "stdout.py", line 14, in a
print "I am here"
File "stdout.py", line 9, in write
traceback.print_stack(file=self.stdout)
Writing '\n'
File "stdout.py", line 19, in <module>
b()
File "stdout.py", line 17, in b
a()
File "stdout.py", line 14, in a
print "I am here"
File "stdout.py", line 9, in write
traceback.print_stack(file=self.stdout)
Если вы идете по этому маршруту, см. также модуль linecache, который вы можете использовать для печати содержимого строки. Взгляните на реализацию traceback.print_stack, чтобы узнать, как это сделать.
Ответ 2
Эта статья может оказаться очень полезной в этом. Найдите события line
и извлеките имя метода из фрейма (если я правильно помню). Более подробную информацию можно найти здесь
Ответ 3
Использовать grep:
grep -rn print .
Ответ 4
Самый простой способ - использовать функцию "debug_print" вместо простой "печати".
Таким образом, вы можете просто переопределить функцию и быть уверенным, что не пропустили один...
и все еще им удобно, если вам нужно снова отлаживать этот код, а не каждый раз редактировать свой код.
(Да, оставляя вызовы debug_print, можно съесть некоторую производительность: просто удалите их, когда это произойдет)
Выделение "только отладочных" инструкций в коде - очень хорошая причина, чтобы сделать diff перед тем, как передать какой-либо код в вашу систему контроля версий! (зная, что добавить ваши комментарии к комментированию в качестве второй веской причины сделать это!)
Ответ 5
Вместо этого используйте функцию printf. Ниже приведено Нечасто ответы на вопросы Python
def printf(format, *args):
"""Format args with the first argument as format string, and print.
If the format is not a string, it is converted to one with str.
You must use printf('%s', x) instead of printf(x) if x might
contain % or backslash characters."""
print str(format) % args,
Теперь, когда вы переходите от отладки к производству, вы переопределяете printf следующим образом:
def printf(format, *args):
pass
Преимущество такого способа заключается в том, что если вам нужно вернуться и сохранить код для добавления функций или исправить ошибку, вы можете снова включить printf.
Ответ 6
Использование grep с искусно сконструированным регулярным выражением (не начинающимся и не заканчивающимся кавычками) кажется лучшим выбором.
Ответ 7
Это, вероятно, не отвечает на ваш вопрос напрямую, но вы можете уйти с множеством операторов печати, если вы используете pdb (отладчик python), чтобы эффективно отлаживать и писать код.
Я знаю, что это работает, потому что 99% времени вы просто не хотите печатать, но вы хотите где-то установить точку останова и посмотреть, что такое переменные и насколько далеко продвинулась программа.
НТН
Ответ 8
Я обычно делаю это в своем коде:
(вверху):
debug=True
(позже)
if debug: print "Это выражение отладки. x =", x
Затем, когда я хочу вынуть всю инструкцию для отладки, я меняю отладку на:
отлаживать = False