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只返回最后一行?documentation说code_context是“ 源代码中的上下文行列表“
我希望code_context包含以下内容:
[
' 1,\n',
' 2,\n',
' 3,\n',
]
我想获得all上下文行。
对于保留空格和注释的健壮解决方案,您可以使用lib2to3
模块从父文件中解析和抓取所有简单的语句节点(在simple_stmt
中以Python语法在Grammar.txt中表示)。框架所属的节点,并返回其起始行号和行数(通过计算换行符的数量计算)覆盖框架的行号的节点:
from lib2to3 import fixer_base, refactor
class ScrapeStatements(fixer_base.BaseFix):
PATTERN = 'simple_stmt'
def __init__(self, *args):
super().__init__(*args)
self.nodes = []
def transform(self, node, _):
self.nodes.append(node)
return node
class Refactor(refactor.RefactoringTool):
def get_fixers(self):
self.scraper = ScrapeStatements(None, None)
return [self.scraper], []
def get_result(self, lineno):
return next(node for node in self.scraper.nodes
if lineno - node.get_lineno() < str(node).count('\n'))
这样:
import inspect
def a(x, y, z):
frame = inspect.stack()[1].frame
refactor = Refactor(None)
refactor.refactor_string(open(frame.f_code.co_filename).read(), '')
print(refactor.get_result(frame.f_lineno))
def b():
a(
1,
2,
3,
)
b()
输出:
a(
1,
2,
3,
)
演示:https://repl.it/@blhsing/HotpinkOpenCgibin
但是,从上面的输出中可以看到,此方法的次要缺点是,如果语句节点位于代码块的开头,则该语句节点将不包含前面的缩进。
不幸的是,Python解释器为每个帧只保留一个行号。查看整个代码上下文的一种相对简单且健壮的方法是使用出色的uncompyle6
模块对代码对象进行反编译。由于代码对象不保留空格和注释,因此您将看到原始代码的更紧凑版本作为反编译输出:
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)