Python3是否有打印类';s方法调用?

Python3是否有打印类';s方法调用?,python,django,Python,Django,是的,我可以手动在每个方法的定义代码开头添加一行print(“call xxx”)。但这似乎有点傻 例如: class Test(): def a(self): return self.b() def b(self): return self.c() def c(self): return 当您使用X处理Test时,然后调用Test().a(),控制台将打印如下内容: call -> a call -> b

是的,我可以手动在每个方法的定义代码开头添加一行
print(“call xxx”)
。但这似乎有点傻

例如:

class Test():
    def a(self):
        return self.b()
    def b(self):
        return self.c()
    def c(self):
        return 
当您使用
X
处理
Test
时,然后调用
Test().a()
,控制台将打印如下内容:

call -> a
call -> b
call -> c
因此,您可以看到方法
a
如何调用其他方法,这有助于理解一些复杂类的逻辑(例如Django的
ListView

首先,我使用元类生成
X
,即:

import functools

def print_info(func):
    @functools.wraps(func)
    def magic(*args,**kwargs):
        print('call -> %s'%func.__name__)
        return func(*args,**kwargs)
    return magic

class BlackMeta(type):
    def __new__(cls, name, parents, attrs):
        new_attrs={}
        for k,v in attrs.items():
            if callable(v):
                new_attrs[k] = print_info(v)
            else:
                new_attrs[k] = v
        return type.__new__(cls, name, parents, new_attrs)

class Test(metaclass=BlackMeta):
    def a(self):
        return self.b()
    def b(self):
        return self.c()
    def c(self):
        return 
它起作用了。但当我将
BlackMeta
添加到
DetailView
的子类中,并调用方法
get
时,出现了错误:


所以我放弃了,来到这里寻求帮助。不一定是元类,任何可以显示方法调用顺序的东西都可以。谢谢。

您可以使用
sys.settrace
注册一个函数,该函数在函数被调用时被调用,如下所示:

import sys

def trace(frame, event, arg):
    if event == 'call':
        print("%s (%s line %d)" % (frame.f_code.co_name, frame.f_code.co_filename, frame.f_lineno))
    return trace

class Test():
    def a(self):
        return self.b()
    def b(self):
        return self.c()
    def c(self):
        return 

def do_stuff():
   t = Test()
   t.a()

sys.settrace(trace)
do_stuff()
输出:

do_stuff (x.py line 16)
a (x.py line 9)
b (x.py line 11)
c (x.py line 13)
只要在任何地方调用任何函数,就会调用跟踪函数,因此
这里的版本将在一个非平凡的程序中产生大量的输出!您只需要在相关的时候打印输出,例如,通过查看
frame.f_code.co_文件名

为什么不使用
inspect
模块()。这允许您查看堆栈并查看父调用链是什么

import inspect

class Test():
    def a(self):
        return self.b()

    def b(self):
        return self.c()

    def c(self):
        print inspect.stack()[0]
        print inspect.stack()[1]
        print inspect.stack()[2]
        return

Test().a()
这将打印出:

(<frame object at 0x100271400>, 'test.py', 9, 'c', ['        print inspect.stack()[0]\n'], 0)
(<frame object at 0x10025dc60>, 'test.py', 7, 'b', ['        return self.c()\n'], 0)
(<frame object at 0x100273a40>, 'test.py', 5, 'a', ['        return self.b()\n'], 0)
(,'test.py',9,'c',['print inspect.stack()[0]\n'],0)
(,'test.py',7,'b',['return self.c()\n'],0)
(,'test.py',5,'a',['return self.b()\n'],0)
在每种情况下,函数名都是每个元组中的第四个项,显然,当您深入堆栈时,您跟踪执行链的距离越远


inspect模块允许进行各种自省,如果您想解开复杂代码的逻辑,它是一个不错的选择。

我如何将其应用于django项目类视图的运行时方法调用?@Pythoner:好问题;您需要尽早调用
settrace
。我不是Django人,但我认为答案可能是在WSGI脚本中完成(如Apache配置文件中指定的)。本文可能会提供足够的线索:最好在定义代码中添加尽可能少的行,但是谢谢still@Pythoner在你的例子中,RichieHindle的答案似乎更合适,但inspect模块可能非常有用。实际上,你的答案更合适。我只需要找到最后一个方法,并在中为I添加一行
[print(I[3])。谢谢。