Python 通过 sys.setprofile 和 frame 检查观察 `str` 调用

标签 python python-3.x

我是 python 框架自省(introspection)的新手,我正在尝试设置分析器或跟踪器以跟踪 str函数调用。我以各种方式设置了跟踪器,但我认为我缺少一些关于帧内省(introspection)和如何获取内置函数名称(即 str)的关键理解

def test_trace():
    sys.setprofile(trace_calls)
    hi = str('hellllo')
    stuff = []
    for i in range(10):
        stuff.append(str(random.randrange(0, 10000000000)))
    print(hi)
    os._exit(0)

def trace_calls(frame, event, arg):
    '''
    if event not in ('call', 'c_call'):
        return
    '''
    stack = collections.deque()
    stack.appendleft(_expand_arg(arg) + _expand_frame(frame))

    while frame.f_back is not None:
        stack.appendleft(_expand_arg(arg) + _expand_frame(frame))
        frame = frame.f_back

    print('-' * 100)
    for frame in stack:
        print(frame)

def _expand_arg(arg):
    if arg is None:
        return ()

    return (
        # arg.__name__,
    )

def _expand_frame(frame):
    code = frame.f_code
    c_class = ''
    c_module = ''
    if 'self' in frame.f_locals:
        c_class = frame.f_locals['self'].__class__.__name__
        c_module = frame.f_locals['self'].__class__.__module__

    return (
        code.co_filename,
        frame.f_lineno,
        frame.f_trace,
        code.co_name,
        code.co_firstlineno,
        c_class,
        c_module,
    )

当我运行 test_trace()我没有看到任何提及 str调用任何配置文件事件。我希望看到有人提到 str<string>在一些调用堆栈中,但只看到随机调用:

$ ipython
Python 3.5.2 (default, Nov 23 2017, 16:37:01)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.4.0 -- An enhanced Interactive Python. Type '?' for help.

('/home/ubuntu/.virtualenvs/papm/lib/python3.5/site-packages/IPython/__init__.py', 125, None, 'start_ipython', 99, '', '')
('/home/ubuntu/.virtualenvs/papm/lib/python3.5/site-packages/traitlets/config/application.py', 658, None, 'launch_instance', 650, '', '')
('/home/ubuntu/.virtualenvs/papm/lib/python3.5/site-packages/IPython/terminal/ipapp.py', 356, None, 'start', 350, 'TerminalIPythonApp', 'IPython.terminal.ipapp')
('/home/ubuntu/.virtualenvs/papm/lib/python3.5/site-packages/IPython/terminal/interactiveshell.py', 485, None, 'mainloop', 478, 'TerminalInteractiveShell', 'IPython.terminal.in
teractiveshell')
('/home/ubuntu/.virtualenvs/papm/lib/python3.5/site-packages/IPython/terminal/interactiveshell.py', 476, None, 'interact', 458, 'TerminalInteractiveShell', 'IPython.terminal.in
teractiveshell')
('/home/ubuntu/.virtualenvs/papm/lib/python3.5/site-packages/IPython/core/interactiveshell.py', 2662, None, 'run_cell', 2636, 'TerminalInteractiveShell', 'IPython.terminal.inte
ractiveshell')
('/home/ubuntu/.virtualenvs/papm/lib/python3.5/site-packages/IPython/core/interactiveshell.py', 2785, None, '_run_cell', 2669, 'TerminalInteractiveShell', 'IPython.terminal.int
eractiveshell')
('/home/ubuntu/.virtualenvs/papm/lib/python3.5/site-packages/IPython/core/interactiveshell.py', 2909, None, 'run_ast_nodes', 2835, 'TerminalInteractiveShell', 'IPython.terminal
.interactiveshell')
('/home/ubuntu/.virtualenvs/papm/lib/python3.5/site-packages/IPython/core/interactiveshell.py', 2963, None, 'run_code', 2933, 'TerminalInteractiveShell', 'IPython.terminal.inte
ractiveshell')
('<ipython-input-2-a29a88804d82>', 1, None, '<module>', 1, '', '')
('/vagrant_data/github.com/dm03514/python-apm/pythonapm/instruments/monkey.py', 35, None, 'test_trace', 30, '', '')
('/home/ubuntu/.virtualenvs/papm/lib/python3.5/random.py', 194, None, 'randrange', 170, 'Random', 'random')
('/home/ubuntu/.virtualenvs/papm/lib/python3.5/random.py', 232, None, '_randbelow', 220, 'Random', 'random')
('/home/ubuntu/.virtualenvs/papm/lib/python3.5/random.py', 232, None, '_randbelow', 220, 'Random', 'random')

('/home/ubuntu/.virtualenvs/papm/lib/python3.5/site-packages/IPython/__init__.py', 125, None, 'start_ipython', 99, '', '')
('/home/ubuntu/.virtualenvs/papm/lib/python3.5/site-packages/traitlets/config/application.py', 658, None, 'launch_instance', 650, '', '')
('/home/ubuntu/.virtualenvs/papm/lib/python3.5/site-packages/IPython/terminal/ipapp.py', 356, None, 'start', 350, 'TerminalIPythonApp', 'IPython.terminal.ipapp')
('/home/ubuntu/.virtualenvs/papm/lib/python3.5/site-packages/IPython/terminal/interactiveshell.py', 485, None, 'mainloop', 478, 'TerminalInteractiveShell', 'IPython.terminal.in
teractiveshell')
('/home/ubuntu/.virtualenvs/papm/lib/python3.5/site-packages/IPython/terminal/interactiveshell.py', 476, None, 'interact', 458, 'TerminalInteractiveShell', 'IPython.terminal.in
teractiveshell')
('/home/ubuntu/.virtualenvs/papm/lib/python3.5/site-packages/IPython/core/interactiveshell.py', 2662, None, 'run_cell', 2636, 'TerminalInteractiveShell', 'IPython.terminal.inte
ractiveshell')
('/home/ubuntu/.virtualenvs/papm/lib/python3.5/site-packages/IPython/core/interactiveshell.py', 2785, None, '_run_cell', 2669, 'TerminalInteractiveShell', 'IPython.terminal.int
eractiveshell')
('/home/ubuntu/.virtualenvs/papm/lib/python3.5/site-packages/IPython/core/interactiveshell.py', 2909, None, 'run_ast_nodes', 2835, 'TerminalInteractiveShell', 'IPython.terminal
.interactiveshell')
('/home/ubuntu/.virtualenvs/papm/lib/python3.5/site-packages/IPython/core/interactiveshell.py', 2963, None, 'run_code', 2933, 'TerminalInteractiveShell', 'IPython.terminal.inte
ractiveshell')
('<ipython-input-2-a29a88804d82>', 1, None, '<module>', 1, '', '')
('/vagrant_data/github.com/dm03514/python-apm/pythonapm/instruments/monkey.py', 35, None, 'test_trace', 30, '', '')
('/home/ubuntu/.virtualenvs/papm/lib/python3.5/random.py', 194, None, 'randrange', 170, 'Random', 'random')
('/home/ubuntu/.virtualenvs/papm/lib/python3.5/random.py', 194, None, 'randrange', 170, 'Random', 'random')

我在 python 内置配置文件中看到了字符串调用 so I tried to look at how they get the c function names ,以防str正在委托(delegate)给 c 电话。

我试图通过检查 arg 来获取 c 函数调用(都有 setprofilesettrace 但它也没有显示任何字符串调用

    if event == "c_call":
        self.c_func_name = arg.__name__

是否有人熟悉如何跟踪 python str或内置调用。

最佳答案

When I run test_trace() I see no mention of any str calls in any of the profiled events.

那是因为 str() 是一个完全用 C 定义的类型对象。只跟踪函数调用,不跟踪类型调用,所以没有c_call 事件被发出。

您可以通过替换内置的 str 来解决这个问题;您可以通过 builtins module 更改 Python 的内置函数:

import builtins

orig_str = builtins.str
def traceable_str(*args):
    return orig_str(*args)
builtins.str = traceable_str

您现在可以看到 traceable_str 调用已传递给分析函数。

但是,请注意,只有从 Python 代码到 str() 的调用才会被跟踪!任何用 C 实现的东西,比如 print() 函数,甚至不调用 str() 内置函数,它只是使用 C API 来实现相同的结果。

关于Python 通过 sys.setprofile 和 frame 检查观察 `str` 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50721746/

相关文章:

python - 使用 lambda 删除一系列 Python 中出现次数低于特定次数的单词

python - “<' not supported between instances of ' 方法”和 'method' - Python、Django

python - 如何在Python的深度嵌套数据结构中找到多次出现的键?

python - 如何获取绑定(bind)键而不在输入框中输入

python - 如何限制 JSONEncoder 产生的 float ?

python - 从另一个列表中查找数字索引

python - Visual Studio 更新到 15.0 后出现扭曲安装问题

python - 使用 numpy 拟合多项式随 dtype 变化,即使实际数据值保持不变

Python win32 Excel 将图表粘贴为位图 (PasteSpecial)?

当持有两个整数骰子时,Python偶尔出现列表索引错误