Нахождение оператора печати в Python - PullRequest
16 голосов
/ 24 октября 2009

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

Sidenote

Похоже, что умный поиск может решить большинство случаев. В Pydev (и других IDE) есть функция поиска, которая позволяет осуществлять поиск по всем файлам в проекте. Конечно, подобный эффект может быть получен при использовании grep с флагом -rn, хотя вместо прямых ссылок вы получаете только номера строк.

«print (» работает намного лучше в моем коде, и часто в операторе печати есть дополнительный текст, который можно искать с помощью регулярного выражения. Наиболее сложный случай, когда вы только что написали print (x), хотя это можно искать регулярное выражение, где значение внутри x не начинается или не заканчивается кавычками (спасибо! BecomingGuro)

Ответы [ 8 ]

33 голосов
/ 25 октября 2009

Вы спрашивали о статических решениях. Вот динамический. Предположим, что вы запускаете код и видите ошибочную печать или запись в 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 чем-то, что сообщает, где находится оператор print. Я буду использовать 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 для деталей, как это сделать.

5 голосов
/ 24 октября 2009

Эта статья может оказаться очень ценной в этом. Найдите события line и извлеките имя метода из фрейма (если я правильно помню). Более подробную информацию можно найти здесь

4 голосов
/ 24 октября 2009

Используйте grep:

grep -rn print .

2 голосов
/ 24 октября 2009

Вместо этого используйте функцию 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.

2 голосов
/ 24 октября 2009

Самый простой способ - использовать функцию "debug_print" вместо простого "print".

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

(Да, выход из вызовов debug_print может снизить производительность: просто удалите их, когда это так)

Определение операторов «только отладка» в вашем коде - очень веская причина сделать diff перед тем, как вводить любой код в вашу систему контроля версий! (Зная, что добавить в комментарии, это вторая веская причина!)

1 голос
/ 24 октября 2009

Лучше всего использовать grep с искусно построенным регулярным выражением (не начинается и не заканчивается кавычками).

0 голосов
/ 24 октября 2009

Обычно я делаю это в своем коде:

(около верха):

debug=True

(позже)

if debug: print "Это оператор отладки. X =", x

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

отлаживать = False

0 голосов
/ 24 октября 2009

Это, вероятно, не дает прямого ответа на ваш вопрос, но вы можете избежать множества операторов печати, если вы используете pdb (отладчик python) для эффективной отладки и написания кода.

Я знаю, что это работает, потому что 99% времени вы просто не хотите печатать материал, но вы хотите где-то установить точку останова и посмотреть, какие переменные и как далеко достигла программа.

НТН

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