Поиск инструкции печати в 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