代码之家  ›  专栏  ›  技术社区  ›  dm03514

python通过sys.setprofile和frame inspection观察“str”调用

  •  6
  • dm03514  · 技术社区  · 6 年前

    我对python框架的内省是全新的,我试图设置一个profiler或tracer来跟踪 str 函数调用。我有各种各样的设置跟踪程序,但我认为我缺少一些关于框架内省和如何获得内置函数名(即 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 正在委派一个C呼叫。

    我试图通过检查 arg (两者兼有) setprofile settrace 但它也没有显示任何字符串调用

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

    有人熟悉如何追踪巨蟒吗 STR 或内置通话。

    1 回复  |  直到 6 年前
        1
  •  2
  •   Martijn Pieters    6 年前

    当我运行test_trace()时,在任何已分析的事件中都看不到任何str调用。

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

    你可以通过替换 str 内置;您可以通过 builtins module :

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

    你现在可以看到 traceable_str 调用被传递到分析函数。

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