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

Я реализую функцию ведения журнала в статический период, и для этого необходимо получить идентификатор, чтобы определить, где вызывается функция. В настоящее время идентификатор вычисляется с помощью сериализации «inspect.stack () [1] [1:]» с помощью «pickle», и я создал ниже скрипт Python для тестирования этой функции. В настоящее время я использую модуль «проверить», но он возвращает только имя файла, номер строки, источник в этой строке.

import inspect
import hashlib


def loginfo_throttle():
    frame = inspect.stack()[1][0]
    print('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
    print(hashlib.md5(pickle.dumps(inspect.stack()[1][1:])).hexdigest())
    print(inspect.getframeinfo(frame))
    print('<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<')


def main():
    loginfo_throttle();loginfo_throttle()
    loginfo_throttle()


if __name__ == '__main__':
    main()

Вывод такой, как показано ниже, а первый и второй вывод точно такие же, и в этом проблема.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
9ab15e3e3d106afca16e4155ac571152
Traceback(filename='spam.py', lineno=20, function='main', code_context=['    loginfo_throttle();loginfo_throttle()\n'], index=0)
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
9ab15e3e3d106afca16e4155ac571152
Traceback(filename='spam.py', lineno=20, function='main', code_context=['    loginfo_throttle();loginfo_throttle()\n'], index=0)
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
2d63d9b94b68ba14989ffebed0b70ab2
Traceback(filename='spam.py', lineno=21, function='main', code_context=['    loginfo_throttle()\n'], index=0)
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Обновить

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

import inspect
import pickle
import time


class LoggingThrottle(object):

    time_table = {}

    def __call__(self, period, msg):
        id = pickle.dumps(inspect.stack()[1][1:])
        now = time.time()
        last_time = self.time_table.get(id)
        if (last_time is None) or ((now - last_time) > period):
            print(msg)
            self.time_table[id] = now


logging_throttle = LoggingThrottle()


def main():
    for i in xrange(1000):
        logging_throttle(3, 'foo'); logging_throttle(3, 'spam')
        logging_throttle(3, 'bar')
        time.sleep(0.1)


if __name__ == '__main__':
    main()

Это выводит только «foo» и «bar».

foo
bar
foo
bar

person Kentaro Wada    schedule 03.06.2016    source источник


Ответы (2)


Вы можете добавить time(), чтобы различать функции, вызываемые в одной строке.

import inspect
import hashlib
import pickle
from time import time


def loginfo_throttle():
    frame = inspect.stack()[1][0]
    print('>'*30)
    t = time()
    print(hashlib.md5(pickle.dumps((t, inspect.stack()[1][1:]))).hexdigest())
    print(t, inspect.getframeinfo(frame))
    print('<'*30)


def main():
    loginfo_throttle();loginfo_throttle()
    loginfo_throttle()


if __name__ == '__main__':
    main()

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
5576395790524ffafbc8e3c257580697
(1464942290.227, Traceback(filename='<ipython-input-70-f8a8af94e830>', lineno=16, function='main', code_context=[u'    loginfo_throttle();loginfo_throttle()\n'], index=0))
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
a56f921a23caef7f5d40713141a53b55
(1464942290.354, Traceback(filename='<ipython-input-70-f8a8af94e830>', lineno=16, function='main', code_context=[u'    loginfo_throttle();loginfo_throttle()\n'], index=0))
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
16e9e10e253c42a4eeb5b5c42911de19
(1464942290.482, Traceback(filename='<ipython-input-70-f8a8af94e830>', lineno=17, function='main', code_context=[u'    loginfo_throttle()\n'], index=0))
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
person Vadim Shkaberda    schedule 03.06.2016
comment
Возможно, это не работает в моем случае. Я обновил вопрос, поэтому прочитайте его в разделе Обновление. - person Kentaro Wada; 03.06.2016
comment
Все, что я могу предложить, это добавить аргумент к id, например. : id = pickle.dumps((msg, inspect.stack()[1][1:])). - person Vadim Shkaberda; 03.06.2016

Я нашел решение, получив столбец в исходном коде, как показано ниже, увидев этот пост. Как найти номер столбца в коде Python

import inspect
import pickle
import time


class LoggingThrottle(object):

    time_table = {}

    def __call__(self, period, msg):
        caller = inspect.stack()[1]
        frame, _, lineno, _, code, _ = caller
        caller_id = (
            inspect.getabsfile(frame),
            code,
            lineno,
            frame.f_lasti,
        )
        # print('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
        # print(caller_id)
        # print('<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<')
        caller_id = pickle.dumps(caller_id)
        now = time.time()
        last_time = self.time_table.get(caller_id)
        if (last_time is None) or ((now - last_time) > period):
            print(msg)
            self.time_table[caller_id] = now


logging_throttle = LoggingThrottle()


def main():
    for i in xrange(1000):
        logging_throttle(3, 'foo'); logging_throttle(3, 'spam')
        logging_throttle(3, 'bar')
        time.sleep(0.1)


if __name__ == '__main__':
    main()
person Kentaro Wada    schedule 03.06.2016