Python inspect.stack () code_context возвращает только одну строку контекста - PullRequest
0 голосов
/ 06 ноября 2019
import inspect

def a(x, y, z):
  frame = inspect.stack()[1]
  print(frame.code_context)

def b():
  a(
    1,
    2,
    3,
  )

b()

>> ['    3,\n']

Почему code_context возвращает только последнюю строку ?? документация говорит, что code_context - это " список строк контекста из исходного кода "

Я бы ожидал, что code_context будет включать что-то вроде:

[
  '    1,\n',
  '    2,\n',
  '    3,\n',
]

Я хотел бы получить все строки контекста.

Ответы [ 2 ]

1 голос
/ 06 ноября 2019

Для надежного решения, которое сохраняет пробелы и комментарии, вы можете использовать модуль lib2to3 для анализа и очистки всех простых узлов операторов (обозначается simple_stmt в грамматике Python из Grammar.txt ) из файла, которому принадлежит родительский фрейм, и возвращает узел, чей номер начальной строки и количество строк (рассчитанное путем подсчета количества символов новой строки) покрывают номер строки фрейма. Обратите внимание, что узел оператора не содержит предшествующего отступа, если он находится в начале блока кода, поэтому вам придется получить отступ от предыдущего узла-брата, если это узел пробелов:

from lib2to3 import fixer_base, refactor

class StatementScraper(fixer_base.BaseFix):
    PATTERN = 'simple_stmt'

    def __init__(self, lineno):
        super().__init__(None, None)
        self.lineno = lineno
        self.statement = ''

    def transform(self, node, result):
        if not self.statement and self.lineno - node.get_lineno() < str(node).count('\n'):
            prev_sibling = str(node.prev_sibling)
            if prev_sibling.isspace():
                self.statement += prev_sibling.lstrip('\n')
            self.statement += str(node)
        return node

class get_statement(refactor.RefactoringTool):
    def __init__(self, source, lineno):
        self.source = source
        self.scraper = StatementScraper(lineno)
        super().__init__(None)

    def get_fixers(self):
        return [self.scraper], []

    def __str__(self):
        self.refactor_string(self.source, '')
        return self.scraper.statement

так что:

import inspect

def a(x, y, z):
    frame = inspect.stack()[1].frame
    print(get_statement(open(frame.f_code.co_filename).read(), frame.f_lineno))

def b():
    a(
        1,
        2,
        3,
    )

b()

выходы:

    a(
        1,
        2,
        3,
    )

Демо: https://repl.it/@blhsing/HotpinkOpenCgibin

0 голосов
/ 06 ноября 2019

К сожалению, интерпретатор Python сохраняет только один номер строки для каждого кадра. Одним из относительно простых и надежных способов просмотра всего контекста кода является декомпиляция объекта кода с использованием превосходного модуля uncompyle6. Поскольку объект кода не сохраняет пробелы и комментарии, в качестве декомпилированного вывода вы увидите более компактную версию исходного кода:

import inspect
from io import StringIO
from uncompyle6 import deparse_code2str

def a(x, y, z):
    frame = inspect.stack()[1]
    code = StringIO()
    deparse_code2str(frame.frame.f_code, out=code)
    print(code.getvalue())

def b():
    a(
        1,
        2,
        3,
    )

b()

. Вывод:

a(1, 2, 3)

Демо: https://repl.it/@blhsing/PastelPunyProcess

...