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