Điều này thực sự phức tạp. Hãy để tôi thử và đưa ra một câu trả lời hoàn chỉnh hơn, sử dụng lại this code và gợi ý về số getargspec
trong câu trả lời của Senthil đã khiến tôi kích hoạt bằng cách nào đó. Thay vào đó, Btw, getargspec
không được dùng trong Python 3.0 và getfullarcspec
should be used.
này làm việc cho tôi trên Python 3.1.2 cả với gọi một cách rõ ràng chức năng debug và với việc sử dụng một trang trí:
# from: https://stackoverflow.com/a/4493322/923794
def getfunc(func=None, uplevel=0):
"""Return tuple of information about a function
Go's up in the call stack to uplevel+1 and returns information
about the function found.
The tuple contains
name of function, function object, it's frame object,
filename and line number"""
from inspect import currentframe, getouterframes, getframeinfo
#for (level, frame) in enumerate(getouterframes(currentframe())):
# print(str(level) + ' frame: ' + str(frame))
caller = getouterframes(currentframe())[1+uplevel]
# caller is tuple of:
# frame object, filename, line number, function
# name, a list of lines of context, and index within the context
func_name = caller[3]
frame = caller[0]
from pprint import pprint
if func:
func_name = func.__name__
else:
func = frame.f_locals.get(func_name, frame.f_globals.get(func_name))
return (func_name, func, frame, caller[1], caller[2])
def debug_prt_func_args(f=None):
"""Print function name and argument with their values"""
from inspect import getargvalues, getfullargspec
(func_name, func, frame, file, line) = getfunc(func=f, uplevel=1)
argspec = getfullargspec(func)
#print(argspec)
argvals = getargvalues(frame)
print("debug info at " + file + ': ' + str(line))
print(func_name + ':' + str(argvals)) ## reformat to pretty print arg values here
return func_name
def df_dbg_prt_func_args(f):
"""Decorator: dpg_prt_func_args - Prints function name and arguments
"""
def wrapped(*args, **kwargs):
debug_prt_func_args(f)
return f(*args, **kwargs)
return wrapped
Cách sử dụng:
@df_dbg_prt_func_args
def leaf_decor(*args, **kwargs):
"""Leaf level, simple function"""
print("in leaf")
def leaf_explicit(*args, **kwargs):
"""Leaf level, simple function"""
debug_prt_func_args()
print("in leaf")
def complex():
"""A complex function"""
print("start complex")
leaf_decor(3,4)
print("middle complex")
leaf_explicit(12,45)
print("end complex")
complex()
và in:
start complex
debug info at debug.py: 54
leaf_decor:ArgInfo(args=[], varargs='args', keywords='kwargs', locals={'args': (3, 4), 'f': <function leaf_decor at 0x2aaaac048d98>, 'kwargs': {}})
in leaf
middle complex
debug info at debug.py: 67
leaf_explicit:ArgInfo(args=[], varargs='args', keywords='kwargs', locals={'args': (12, 45), 'kwargs': {}})
in leaf
end complex
Trình trang trí cheats một chút: Vì trong số wrapped
chúng tôi nhận được cùng một rguments là chức năng chính nó nó không quan trọng mà chúng tôi tìm thấy và báo cáo ArgSpec của wrapped
trong getfunc
và debug_prt_func_args
. Mã này có thể được làm đẹp một chút, nhưng nó hoạt động ngay bây giờ cho các testcases gỡ lỗi đơn giản mà tôi đã sử dụng. Bạn có thể thấy rằng inspect
có thể cung cấp cho bạn "ngữ cảnh" thực sự là dòng mã nguồn mà một hàm được gọi.Mã này rõ ràng không hiển thị nội dung của bất kỳ biến nào được gán cho hàm của bạn, nhưng đôi khi nó đã giúp biết tên biến được sử dụng một cấp ở trên hàm được gọi của bạn.
Như bạn thấy, với trình trang trí, bạn không phải thay đổi mã bên trong hàm.
Có thể bạn sẽ muốn in đẹp các arg. Tôi đã để lại bản in thô (và cũng là một nhận xét in ra nhận xét) trong chức năng vì vậy nó dễ dàng hơn để chơi xung quanh với.
Thật tuyệt vời và đơn giản! Nhưng tôi sẽ không nhớ phức tạp hơn nếu nó có nghĩa là tôi không phải lặp lại mỗi tên biến hai lần: một lần là tên arg từ khóa, và một lần là giá trị đối số từ khóa. – max
Bạn có thể thử gọi 'debug (** locals())'. –