1

I want to write a decorator in python: if a called function contains print's, the decorator prints her name before this function being called. I'm familiar with decorators syntax, but I have a problem with checking if a function has print within itself.

def preceeding_name(func):        
    @wraps(func)
    def wrapper(*args, **kwargs):
        if 'print' in func: 
            print(func.__name__)
        result = func(*args, **kwargs)
        return result
    return wrapper

It is not necessary to check if the print's from function will actually be called.

3
  • Finding out if a function calls another function is hard. Can I suggest that you use the logging module instead? You can then easily use something like %(funcName)s when creating a formatter. Commented Feb 28, 2017 at 13:39
  • @Josh, thank you, I will look at this functional Commented Feb 28, 2017 at 13:48
  • This can be done by overriding sys.stdout Commented Feb 28, 2017 at 14:14

2 Answers 2

3

This can be done by holding the buffer of 'print' from flushing and checking it to see if a print has been done.

class Out(object):
    def write(self,s):
        self.s += s
    def __init__(self)
        self.s = '' 

Now to check

def wrapper(*args, **kwargs):
        our_out = Out()
        sys.stdout = our_out
        result = func(*args, **kwargs)

        if len(our_out.s)>0:
            sys.stdout = sys.__stdout__
            print func.__name__
            for s in our_out.s.split('\n'):
                print s     

        return result
Sign up to request clarification or add additional context in comments.

Comments

-1

I this case you can redefine print

def preceeding_name(func):
    @wraps(func)
    def wrapper(*args, **kwargs):

        old_print = print

        def print(*arg, **kwarg):
            old_print(func.__name__)
            old_print(*arg, **kwarg)

        result = func(*args, **kwargs)
        return result
    return wrapper

EDIT: i test and this work

old_print = print

def preceeding_name(func):

    def print(*arg, **kwarg):
        old_print(func.__name__, end='')
        old_print(*arg, **kwarg)

    def wrapper(*args, **kwargs):
        print('')
        result = func(*args, **kwargs)
        return result
    return wrapper

@preceeding_name
def a():
    print('hi')


a()

@preceeding_name
def b():
    print('hi')


b()

EDIT2:

old_print = print


def preceeding_name(func):
    global print
    def print(*arg, **kwarg):
        old_print(func.__name__)
        old_print(*arg, **kwarg)

    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result

    return wrapper


@preceeding_name
def a():
    print('hi')


a()


@preceeding_name
def b():
    # print('hi')
    pass

b()

5 Comments

This decorator doesn't do anything at all. Just because you redefine print in your current scope doesn't mean the decorated function will also use the new print.
@Rawing new edit of my code work in my computer. i use python 3.4
This doesn't check if the function ever calls print.
No, this doesn't really work either. This replaces print globally, which means undecorated functions will also use the new print. And it'll only work if the decorator is in the same file as the decorated function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.