Модуль трассировки Python - отслеживает строки по мере их выполнения, но сохраняет в файл, а не в стандартный вывод.

Я хочу отслеживать строки скрипта Python по мере их выполнения. Однако программа, которую я использую, должна выводить данные на стандартный вывод. Параметр трассировки модуля трассировки python выводит их на стандартный вывод. Можно ли сказать, чтобы он не печатал их в стандартный вывод, а вместо этого сохранял в файл? Я пробовал установить параметр outfile, но он не останавливает печать линий трассировки.


person Rory    schedule 26.11.2010    source источник


Ответы (5)


Вы можете скопировать код модуля трассировки и внести несколько изменений, чтобы заставить его записывать выходные данные в файл по вашему выбору. Между строками 600 и 650 есть пять операторов print, которые вы хотите изменить. Поскольку вам не нужно делать его слишком красивым, вы можете добавить это в самый конец файла:

my_out_file = open("/home/mytrace.txt", "w")

и измените операторы печати так:

print "%s(%d): %s" % (bname, lineno,
                      linecache.getline(filename, lineno)),

становится это:

print >>my_out_file, "%s(%d): %s" % (bname, lineno,
                      linecache.getline(filename, lineno)),
person Ned Batchelder    schedule 26.11.2010
comment
в случае сбоя вам, вероятно, следует включить буферизацию строк open(..., buffering=1) - person ti7; 18.06.2021

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

Модуль трассировки продолжит вывод информации трассировки на стандартный вывод.

Для ручной трассировки, если есть функция входа, я использовал sys.settrace для выполнения работы по отслеживанию потоков вызовов. Его можно расширить, чтобы отслеживать выполнение построчно. Вы всегда можете записать информацию в файл, а не печатать ее на стандартный вывод.

Простая структура - это

import sys
import os
import linecache

trace_depth = 0

def trace(f):

    def globaltrace(frame, why, arg):
        global trace_depth
        if why == "call":
            # function call event , extract information
            .....
            pass

            trace_depth = trace_depth + 1
        return None

    def localtrace(frame, why, arg):
        global trace_depth
        if why == "line":
            # line execution event
            pass
        elif why == "return":
            trace_depth = trace_depth - 1
            # function return event
        return localtrace

    def _f(*args, **kwds):
        sys.settrace(globaltrace)
        result = f(*args, **kwds)
        sys.settrace(None)
        return result

    return _f

globaltrace и localtrace - это функции обратного вызова, которые вызываются с событием "почему".

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

if why == "call":
    # Parent frame details
    p_func = frame.f_back.f_code.co_name
    p_file = frame.f_back.f_code.co_filename
    p_lineinfo = frame.f_back.f_lineno

Полную информацию я опубликовал здесь.

person pyfunc    schedule 26.11.2010
comment
Есть ли какой-либо другой модуль, который может сохранять данные трассировки в файл? - person Rory; 26.11.2010
comment
@ Рори: Как вы отслеживаете казнь? Какую командную строку вы используете? Раньше я использовал трассировку вручную, изменяя вывод по своему вкусу. - person pyfunc; 26.11.2010
comment
Спасибо за ваш ответ. Это много кода. Есть ли поддерживаемая библиотека, которая могла бы здесь помочь? - person guettli; 08.07.2021

Может случиться так, что вам понадобится так называемая «трассировка функции», описанная для PHP. Я создал инструмент Python, который производит аналогичный вывод с использованием хука pyfunc sys.settrace ().

person anatoly techtonik    schedule 27.10.2011

Вы вызываете трассировку в командной строке? Если это так, я рекомендую использовать стандартный метод перенаправления любого stdout в любой файл. Перенаправить весь вывод в файл

foo > allout.txt 2>&1

Я уверен, что в Windows есть что-то подобное, если вы находитесь в Windows.

person melchoir55    schedule 14.04.2015
comment
Я думаю, OP хотел, чтобы собственный стандартный вывод программы по-прежнему находился в обычном месте. - person Edward Falk; 16.10.2019

Другая возможность, когда вы используете stdout / stderr для чего-то еще, - это запустить поток для записи и отправки сообщений в очередь

import threading
from queue import Queue

def worker(Q, file_dest):
    with open(file_dest, "r+", buffering=1) as fh:
        while True:
            fh.write(f"{}\n".format(Q.get()))

...
    dest_file = "some-writeable/path.txt"
    Q = Queue()  # can be a global, but please name it better!
    t = threading.Thread(
        worker,
        args=(Q, dest_file),
        daemon=True,  # don't block exit
    )
    # set t.daemon = True here instead in earlier Python
    t.start()

всякий раз, когда вы хотите написать, используйте метод .put()

Q.put("some message")

buffering=1 используется для буферизации строк

person ti7    schedule 18.06.2021