为什么提供的 Python 脚本不打印其跟踪代码的所有行?

问题描述 投票:0回答:1

虽然使用了 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 行。

python trace
1个回答
0
投票

最简单的解释是第 5 行和第 8 行没有执行,因为它们是先前执行的行的延续。结尾的 ')' 只是第 3 行或第 6 行的一部分,没有任何可执行的内容。同样,代码中要执行的任何额外行都不会被跟踪为空行。

作为演示,我对您的示例进行了一些调整,包括以下内容:

  1. 对于初始打印语句,我使用隐式连接和 + 运算符将要打印的字符串扩展到多行。不跟踪隐式连接,而跟踪带有 + 运算符的行。
  2. 我还向函数添加了一个 f 字符串标注,它确实有自己的跟踪线。
  3. 我还在自己的行中添加了 sep 和 end 参数
  4. 我将“再见”行的输入参数更改为多行字符串。仅跟踪多行字符串的开头
  5. 我在末尾添加了一个额外的打印调用,带有多个输入参数,以及 end 和 sep 参数。它只被追踪一次,而不是每个参数一次。
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'
© www.soinside.com 2019 - 2024. All rights reserved.