虽然使用了 5 岁时提供的略微修改过的代码,但直到今天我才回答了问题如何在执行 python 脚本时打印每一行(包括控制台)? 我遇到了详细理解问题代码有效,尤其是为什么跟踪跳过提到运行第 5 和第 8 行?
我知道存在另一种跟踪脚本执行情况的方法
python3 -m trace --trace --ignore-module sys,time --ignore-dir /sys:/usr tmp.py
但我希望可以选择根据我的需要调整打印的输出内容和格式,并详细了解代码的工作原理,以便解释为什么并非所有已执行代码行都出现在跟踪中。
请对我的问题感到鼓舞,提供另一个更好的代码答案(不是像下面这个那样的肮脏的黑客)作为对我的问题开始的另一个问题的回应。
代码下方:
import subprocess
tracerCode = """
import sys
import inspect
class SetTrace(object):
'''Although, this produces the desired result, it is
a very bad hack since it will most likely break depending on what
python_string_base is'''
def __init__(self, func):
self.func = func
def __enter__(self):
sys.settrace(self.func)
return self
def __exit__(self, ext_type, exc_value, traceback):
sys.settrace(None)
def monitor(frame, event, arg):
if event == "line":
file_dict = dict(enumerate("{}".split("|")))
line_number = frame.f_lineno-30 # Amount of lines in THIS string
if line_number > 0:
print( "line " + str(line_number)+ ": " + file_dict[line_number] )
sys.stdout.flush()
return monitor
def run():
{}
with SetTrace(monitor):
run()
"""
codeToRun = """
import time
for _ in range(1):
print(
'hello'
)
time.sleep(
5
)
print ( 'goodbye')
"""
tracerCode = tracerCode.format("|".join([i.strip() for i in codeToRun.split("\n")]), codeToRun)
#print(tracerCode)
proc = subprocess.Popen(['python3.11', '-'], stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
proc.stdin.write(bytes(tracerCode,"utf-8"))
proc.stdin.close()
for line in proc.stdout:
print( '{}'.format(line.strip()) )
proc.wait()
印刷
b'line 1: import time'
b'line 2: for _ in range(1):'
b'line 3: print('
b"line 4: 'hello'"
b'line 3: print('
b'hello'
b'line 6: time.sleep('
b'line 7: 5'
b'line 6: time.sleep('
b'line 2: for _ in range(1):'
b"line 9: print ( 'goodbye')"
b'goodbye'
输出中未包含第 5 行和第 8 行。
最简单的解释是第 5 行和第 8 行没有执行,因为它们是先前执行的行的延续。结尾的 ')' 只是第 3 行或第 6 行的一部分,没有任何可执行的内容。同样,代码中要执行的任何额外行都不会被跟踪为空行。
作为演示,我对您的示例进行了一些调整,包括以下内容:
import subprocess
tracerCode = """
import sys
import inspect
class SetTrace(object):
'''Although, this produces the desired result, it is
a very bad hack since it will most likely break depending on what
python_string_base is'''
def __init__(self, func):
self.func = func
def __enter__(self):
sys.settrace(self.func)
return self
def __exit__(self, ext_type, exc_value, traceback):
sys.settrace(None)
def monitor(frame, event, arg):
if event == "line":
file_dict = dict(enumerate("{}".split("|")))
line_number = frame.f_lineno-30 # Amount of lines in THIS string
if line_number > 0:
print( "line " + str(line_number)+ ": " + file_dict[line_number] )
sys.stdout.flush()
return monitor
def run():
{}
with SetTrace(monitor):
run()
"""
codeToRun = """
import time
def word():
return 'today'
for _ in range(1):
print(
'hello '
'world '
'how ' + 'are ' + 'you '
f'{word()}?',
end=';\\n',
sep='--'
)
time.sleep(
5
)
print ( '''
goodbye
cruel
world
'''
)
print('Testing1', 'testing2', 'testing3', sep=' - ', end='FIN')
"""
tracerCode = tracerCode.format("|".join([i.strip() for i in codeToRun.split("\n")]), codeToRun)
#print(tracerCode)
proc = subprocess.Popen(['python3.11', '-'], stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
proc.stdin.write(bytes(tracerCode,"utf-8"))
proc.stdin.close()
for line in proc.stdout:
print( '{}'.format(line.strip()) )
proc.wait()
给出输出:
b'line 1: import time'
b'line 3: def word():'
b'line 6: for _ in range(1):'
b'line 7: print('
b"line 8: 'hello '"
b"line 10: 'how ' + 'are ' + 'you '"
b"line 11: f'{word()}?',"
b"line 4: return 'today'"
b"line 10: 'how ' + 'are ' + 'you '"
b"line 8: 'hello '"
b"line 12: end=';"
b"',"
b"line 13: sep='--'"
b'line 7: print('
b'hello world how are you today?;'
b'line 15: time.sleep('
b'line 16: 5'
b'line 15: time.sleep('
b'line 6: for _ in range(1):'
b"line 18: print ( '''"
b''
b'goodbye'
b'cruel'
b'world'
b''
b"line 25: print('Testing1', 'testing2', 'testing3', sep=' - ', end='FIN')"
b'Testing1 - testing2 - testing3FIN'