2017-09-01 59 views
2

我有以下的通用調試器:從函數聲明收集帕拉姆名稱

def debugger(method): 

    def dec(*args, **kwargs): 
     print("\ndebugging '{name}':\n".format(name=method.__name__)) 
     FOUR_SPACES = " " * 4 
     EIGHT_SPACES = " " * 8 
     if args: 
      print("{four}args:\n".format(four=FOUR_SPACES)) 
      for arg in args: 
       print("%s%s" % (EIGHT_SPACES, arg)) 
     if kwargs: 
      for key, value in kwargs.items(): 
       print("{four}{key}:\n{eight}{value}\n".format(
        four=FOUR_SPACES, 
        key=key, 
        eight=EIGHT_SPACES, 
        value=value 
       )) 

     if args or kwargs: 
      print("\n") 

     result = method(*args, **kwargs) 
     return result 

    return dec 

@debugger 
def generate_minutes_in_timespan(start, end, cutoff_date=None): 
    # cutoff_date is just example of kwarg 
    minutes_delta = (end - start).seconds/60 
    datetimes = [] 
    delta_range = range(0, minutes_delta + 1) 
    return [start + timedelta(minutes=i) for i in delta_range] 

調試器會做:

debugging 'generate_minutes_in_timespan': 

    args: 

     2017-08-31 17:19:00 
     2017-09-01 12:05:00 

這讓我高興略有下降,但發現我錯過了真實的信息。

我要的是:

debugging 'generate_minutes_in_timespan': 

    args: 

     start = 2017-08-31 17:19:00 
     end = 2017-09-01 12:05:00 

    *args: 

     not allowed 

    kwargs: 

     cutoff_date = None 

    *kwargs: 

     not allowed 

那些ARGS有語義,並且可以作爲startend ......他們不是*args

有很深的Python標準庫,我可以讀這個方法generate_minutes_in_timespan和採摘關報關,名稱和所需位置參數的個數順序,任何宣稱kwargs(類似於聲明cutoff_date=None還名稱的方式,我會想知道cutoff_date作爲kwarg提供,vs可選**kwargs ...)

我爲{'args': [('start', 'the value given'), ('end', 'the user given value')], 'star_args': None, 'kwargs': {'cutoff_date': None}, 'star_kwargs': None}拍攝了完整的調試信息。

謝謝

回答

4

從裝飾中,使用inspect模塊來發現ARG名稱:

>>> def generate_minutes_in_timespan(start, end, cutoff_date=None): 
...  ... 
... 
>>> inspect.getargspec(generate_minutes_in_timespan) 
ArgSpec(args=['start', 'end', 'cutoff_date'], varargs=None, keywords=None, defaults=(None,)) 
      ^ ^
       |________|_____ here they are... 

匹配了實際ARG名稱傳遞的參數留作練習了OP。

3

使用inspect.signature(method).bind

for name, val in inspect.signature(method).bind(*args, **kwargs).arguments: 
    print('{} = {}'.format(name, val)) 

如果你在Python 2中,還有的PyPI上的這個功能,你可以使用一個backport

+0

我覺得用戶是在PY 2,因爲他們依靠'/'一個整數除法。對於py 3用戶,這絕對是比我更好的答案。 – wim

1

結果是好的:

import inspect 

def debugger(method): 

    def dec(*args, **kwargs): 
     print("\ndebugging '{name}':\n".format(name=method.__name__)) 
     FOUR_SPACES = " " * 4 
     EIGHT_SPACES = " " * 8 

     inspector = inspect.getargspec(method) 

     arg_names = inspector.args 
     var_args = inspector.varargs 
     keyword_args = inspector.keywords 

     def wrap_string_in_quotes(value): 
      if isinstance(value, str): 
       return '"' + value + '"' 
      else: 
       return value 

     if args: 
      print("{four}args:\n".format(four=FOUR_SPACES)) 
      for index, arg_name in enumerate(arg_names): 
       print(
        "{eight}{name} = {arg}" \ 
        .format(
         eight=EIGHT_SPACES, 
         name=arg_name, 
         arg=wrap_string_in_quotes(args[index]) 
        ) 
       ) 

     if var_args: 
      start = len(arg_names) 
      these_args = args[start:] 
      print("\n{four}*{star_arg_name}:\n".format(four=FOUR_SPACES, star_arg_name=var_args)) 
      for this_var_arg in these_args: 
       print("{eight}{arg}".format(eight=EIGHT_SPACES, arg=wrap_string_in_quotes(this_var_arg))) 

     if kwargs: 
      print("\n{four}**{kwargs_name}:\n".format(four=FOUR_SPACES, kwargs_name=keyword_args)) 
      for key, value in kwargs.items(): 
       print("{eight}{key} = {value}\n".format(
        eight=EIGHT_SPACES, 
        key=key, 
        value=wrap_string_in_quotes(value) 
       )) 

     if args or kwargs: 
      print("\n") 

     result = method(*args, **kwargs) 
     return result 

    return dec 


@debugger 
def one_two_kwarg_three_star_args_star_kwargs(one, two, three=None, *args, **kwargs): 
    pass 

one_two_kwarg_three_star_args_star_kwargs(1, 2, 3, 'star arg 1', 'star arg 2', blah='blah, kwarg') 

確實

$ python debugger.py 

debugging 'one_two_kwarg_three_star_args_star_kwargs': 

    args: 

     one = 1 
     two = 2 
     three = 3 

    *args: 

     "star arg 1" 
     "star arg 2" 

    **kwargs: 

     blah = "blah, kwarg"