def print_func_call(ignore_first_arg=False, max_call_number=100):
    """ utility function to facilitate debug, it will print input args before
    function call, and print return value after function call

    usage:

        @print_func_call
        def some_func_to_be_debu():
            pass

    :param ignore_first_arg: whether print the first arg or not.
    useful when ignore the `self` parameter of an object method call
    """
    from functools import wraps

    def display(x):
        x = to_string(x)
        try:
            x.decode('ascii')
        except BaseException:
            return 'NON_PRINTABLE'
        return x

    local = {'call_number': 0}

    def inner(f):

        @wraps(f)
        def wrapper(*args, **kwargs):
            local['call_number'] += 1
            tmp_args = args[1:] if ignore_first_arg and len(args) else args
            this_call_number = local['call_number']
            print(('{0}#{1} args: {2}, {3}'.format(
                f.__name__,
                this_call_number,
                ', '.join([display(x) for x in tmp_args]),
                ', '.join(display(key) + '=' + to_string(value)
                          for key, value in kwargs.items())
            )))
            res = f(*args, **kwargs)
            print(('{0}#{1} return: {2}'.format(
                f.__name__,
                this_call_number,
                display(res))))

            if local['call_number'] > 100:
                raise Exception("Touch max call number!")
            return res
        return wrapper
    return inner
def print_func_call ( ignore_first_arg = False , max_call_number = 100 ) : from functools import wraps def display ( x ) : x = to_string ( x ) try : x . decode ( 'ascii' ) except BaseException : return 'NON_PRINTABLE' return x local = { 'call_number' : 0 } def inner ( f ) : @ wraps ( f ) def wrapper ( * args , ** kwargs ) : local [ 'call_number' ] += 1 tmp_args = args [ 1 : ] if ignore_first_arg and len ( args ) else args this_call_number = local [ 'call_number' ] print ( ( '{0}#{1} args: {2}, {3}' . format ( f . __name__ , this_call_number , ', ' . join ( [ display ( x ) for x in tmp_args ] ) , ', ' . join ( display ( key ) + '=' + to_string ( value ) for key , value in kwargs . items ( ) ) ) ) ) res = f ( * args , ** kwargs ) print ( ( '{0}#{1} return: {2}' . format ( f . __name__ , this_call_number , display ( res ) ) ) ) if local [ 'call_number' ] > 100 : raise Exception ( "Touch max call number!" ) return res return wrapper return inner
utility function to facilitate debug, it will print input args before
    function call, and print return value after function call

    usage:

        @print_func_call
        def some_func_to_be_debu():
            pass

    :param ignore_first_arg: whether print the first arg or not.
    useful when ignore the `self` parameter of an object method call