确定当前行的缩进级别 运行 Python 代码
Determine indentation level of line currently running Python Code
是否可以在程序 运行ning 时确定 Python 中一行的缩进级别?我希望能够根据 运行.
脚本的大纲结构来组织日志文件
在下面的示例中,'first message' 函数将生成 0,'second message' 将生成 1,'third message' 2 并且 'fourth, fifth, sixth' 消息将生成 0
logger.debug('First message')
if True:
logger.info('Second message')
if True:
logger.info('Third message')
logger.warning('Fourth message')
logger.error('Fifth message')
logger.critical('Sixth message')
相应的日志文件如下所示:
First message
Second message
Third message
Fourth message
Fifth message
Sixth message
我能够使用 inspect.getouterframes() 函数确定缩进级别。这假定使用 4 个 ' ' 字符而不是 '\t' 字符进行缩进。
import inspect
def getIndentationLevel():
# get information about the previous stack frame
frame, filename, line_number,function_name, lines, index = inspect.getouterframes(inspect.currentframe())[1]
# count the number of characters in the line
original_length = len(lines[0])
# trim the line of left spaces and record the new length
new_length = len(lines[0].lstrip())
# take the difference between the two values and divide by 4 to get the level number
return int((original_length - new_length) / 4)
首先,我检索调用者的代码上下文:
import inspect
context = inspect.getframeinfo(frame.f_back).code_context
这给了我一个代码行列表;除了第一行,我忽略了所有行。然后我使用正则表达式来获取这一行开头的空格;如果您使用的是制表符,则必须先将它们替换为适当数量的空格:
import re
indent = re.compile("^ *")
firstline = context[0]
firstline = firstline.replace("\t", " ")
match = indent.match(firstline)
出于测试目的,我用点替换了空格,这样我就可以看到发生了什么,并构建我的前缀:
white = "." * match.span(0)[1] # Change "." to " "!
现在我可以用它来修改我的消息msg
我发送到我的记录器:
do_some_logging(white + msg)
如果我可以简单地用一个装饰器包装一个现有的记录器,把这个记录器变成一个空白感知的记录器,那就太好了。假设出于测试目的,我有一个非常原始的记录器,它只是将消息打印到标准输出:
def pseudo_logger(msg):
"""Pseudo-logging function."""
print(msg)
这个记录器有一个记录消息的第一个参数,可能还有一些其他的位置参数和关键字。我想为这样的功能写一个装饰器:
from functools import wraps
def indented(func):
"""Turns the logger func(msg) into an indented logger."""
@wraps(func)
def wrapped(msg, *args, **kwargs):
# ... compute white ...
func(white + msg, *args, **kwargs)
return wrapped
现在我可以获得一个新的记录器,例如:
new_logger = intented(pseudo_logger)
将它们放在一起得出:
from functools import wraps
import inspect
import re
def indented(func):
"""Turns the logger func(msg) into an indented logger."""
indent = re.compile("^ *")
@wraps(func)
def wrapped(msg, *args, **kwargs):
frame = inspect.currentframe()
context = inspect.getframeinfo(frame.f_back).code_context
firstline = context[0]
match = indent.match(firstline)
white = "." * match.span(0)[1] # Change "." to " "!
func(white + msg, *args, **kwargs)
return wrapped
@indented
def pseudo_logger(msg):
"""Pseudo-logging function."""
print(msg)
def main():
pseudo_logger("This is an indented message!")
if True:
pseudo_logger("Another message, but more indented!")
pseudo_logger("This "
"will ignore the indention of the second "
"or third line.")
if __name__ == "__main__":
main()
不过,我会犹豫要不要在生产代码中使用它。像这样使用代码检查是脆弱的,并且根据您调用它的位置,它可能会导致意想不到的效果。
是否可以在程序 运行ning 时确定 Python 中一行的缩进级别?我希望能够根据 运行.
脚本的大纲结构来组织日志文件在下面的示例中,'first message' 函数将生成 0,'second message' 将生成 1,'third message' 2 并且 'fourth, fifth, sixth' 消息将生成 0
logger.debug('First message')
if True:
logger.info('Second message')
if True:
logger.info('Third message')
logger.warning('Fourth message')
logger.error('Fifth message')
logger.critical('Sixth message')
相应的日志文件如下所示:
First message
Second message
Third message
Fourth message
Fifth message
Sixth message
我能够使用 inspect.getouterframes() 函数确定缩进级别。这假定使用 4 个 ' ' 字符而不是 '\t' 字符进行缩进。
import inspect
def getIndentationLevel():
# get information about the previous stack frame
frame, filename, line_number,function_name, lines, index = inspect.getouterframes(inspect.currentframe())[1]
# count the number of characters in the line
original_length = len(lines[0])
# trim the line of left spaces and record the new length
new_length = len(lines[0].lstrip())
# take the difference between the two values and divide by 4 to get the level number
return int((original_length - new_length) / 4)
首先,我检索调用者的代码上下文:
import inspect
context = inspect.getframeinfo(frame.f_back).code_context
这给了我一个代码行列表;除了第一行,我忽略了所有行。然后我使用正则表达式来获取这一行开头的空格;如果您使用的是制表符,则必须先将它们替换为适当数量的空格:
import re
indent = re.compile("^ *")
firstline = context[0]
firstline = firstline.replace("\t", " ")
match = indent.match(firstline)
出于测试目的,我用点替换了空格,这样我就可以看到发生了什么,并构建我的前缀:
white = "." * match.span(0)[1] # Change "." to " "!
现在我可以用它来修改我的消息msg
我发送到我的记录器:
do_some_logging(white + msg)
如果我可以简单地用一个装饰器包装一个现有的记录器,把这个记录器变成一个空白感知的记录器,那就太好了。假设出于测试目的,我有一个非常原始的记录器,它只是将消息打印到标准输出:
def pseudo_logger(msg):
"""Pseudo-logging function."""
print(msg)
这个记录器有一个记录消息的第一个参数,可能还有一些其他的位置参数和关键字。我想为这样的功能写一个装饰器:
from functools import wraps
def indented(func):
"""Turns the logger func(msg) into an indented logger."""
@wraps(func)
def wrapped(msg, *args, **kwargs):
# ... compute white ...
func(white + msg, *args, **kwargs)
return wrapped
现在我可以获得一个新的记录器,例如:
new_logger = intented(pseudo_logger)
将它们放在一起得出:
from functools import wraps
import inspect
import re
def indented(func):
"""Turns the logger func(msg) into an indented logger."""
indent = re.compile("^ *")
@wraps(func)
def wrapped(msg, *args, **kwargs):
frame = inspect.currentframe()
context = inspect.getframeinfo(frame.f_back).code_context
firstline = context[0]
match = indent.match(firstline)
white = "." * match.span(0)[1] # Change "." to " "!
func(white + msg, *args, **kwargs)
return wrapped
@indented
def pseudo_logger(msg):
"""Pseudo-logging function."""
print(msg)
def main():
pseudo_logger("This is an indented message!")
if True:
pseudo_logger("Another message, but more indented!")
pseudo_logger("This "
"will ignore the indention of the second "
"or third line.")
if __name__ == "__main__":
main()
不过,我会犹豫要不要在生产代码中使用它。像这样使用代码检查是脆弱的,并且根据您调用它的位置,它可能会导致意想不到的效果。