В python есть ли способ автоматически регистрировать информацию каждый раз, когда вы создаете переменную? - PullRequest
0 голосов
/ 11 июля 2020

Не уверен, что это вообще имеет смысл, но вот пример:

Допустим, у меня есть сценарий. В этом скрипте я создаю список

list = [1,2,3,4]

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

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

Ответы [ 2 ]

1 голос
/ 11 июля 2020

это хакерство, но какого черта

class _LoggeryType(type):
     def __setattr__(cls,attr,value):
         print("SET VAR: {0} = {1}".format(attr,value))
         globals().update({attr:value})

# Python3
class Loggery(metaclass=_LoggeryType):
      pass

# python2
class Loggery:
    __metaclass__=_LoggeryType



Loggery.x = 5
print("OK set X={0}".format(x))

обратите внимание, я бы не рекомендовал использовать это

0 голосов
/ 11 июля 2020

Один из способов - использовать мощный sys.settrace. Я написал небольшой (но несколько неполный) пример:

tracer.py:

import inspect
import sys
import os
import logging

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger('tracing-logger')

FILES_TO_TRACE = [os.path.basename(__file__), 'tracee.py']
print(FILES_TO_TRACE)

def new_var(name, value, context):
    logger.debug(f"New {context} variable called {name} = {value}")
    # do some analysis here, for example
    if type(value) == list:
        logger.debug(f"\tNumber of elements: {len(value)}")

def changed_var(name, value, context):
    logger.debug(f"{context} variable called {name} of was changed to: {value}")

def make_tracing_func():
    current_locals = {}
    current_globals = {}
    first_line_executed = False

    def tracing_func(frame, event, arg):
        nonlocal first_line_executed

        frame_info = inspect.getframeinfo(frame)
        filename = os.path.basename(frame_info.filename)
        line_num = frame_info.lineno

        if event == 'line':
            # check for difference with locals
            for var_name in frame.f_code.co_varnames:
                if var_name in frame.f_locals:
                    var_value = frame.f_locals[var_name]
                    if var_name not in current_locals:
                        current_locals[var_name] = var_value
                        new_var(var_name, var_value, 'local')
                    elif current_locals[var_name] != var_value:
                        current_locals[var_name] = var_value
                        changed_var(var_name, var_value, 'local')

            for var_name, var_value in frame.f_globals.items():
                if var_name not in current_globals:
                    current_globals[var_name] = var_value
                    if first_line_executed:
                        new_var(var_name, var_value, 'global')

                elif current_globals[var_name] != var_value:
                    current_globals[var_name] = var_value
                    changed_var(var_name, var_value, 'global')

            first_line_executed = True
            return tracing_func

        elif event == 'call':
            if os.path.basename(filename) in FILES_TO_TRACE:
                return make_tracing_func()
        return None

    return tracing_func


sys.settrace(make_tracing_func())
import tracee

tracee.py

my_list = [1, 2, 3, 4]
a = 3
print("tracee: I have a list!", my_list)
c = a + sum(my_list)
print("tracee: A number:", c)
c = 12
print("tracee: I changed it:", c)

Вывод:

DEBUG:tracing-logger:New global variable called my_list = [1, 2, 3, 4]
DEBUG:tracing-logger:   Number of elements: 4
DEBUG:tracing-logger:New global variable called a = 3
tracee: I have a list! [1, 2, 3, 4]
DEBUG:tracing-logger:New global variable called c = 13
tracee: A number: 13
DEBUG:tracing-logger:global variable called c was changed to: 12
tracee: I changed it: 12

Есть некоторые дополнительные случаи, которые вы можете захотеть обработать (дублированные изменения глобальных объектов из-за вызовов функций, закрывающих переменных и т. Д. c.). Вы также можете использовать linecache для поиска содержимого строк или использовать переменную line_num в журнале.

...