3

I have a script which different people may use. I have print statements so people can follow along what the script is doing, and if it breaks where it went wrong, and if a certain step takes a long time which step it was.

Which way for print statements is better in this case and why?

This:

def do_something():
    ...

print 'doing something'
do_something()

Or this:

def do_something():
    print 'doing something'
    ...

do_something()

I am inclined to think the first is better as it is slightly clearer what is going on when people look at your script; they know there is a print statement before the function is called, and you can add extra detail when sometimes the function name isn't as informative as it could be.

However I see how it could be considered duplication of code. And so the second is better.

But more important than this quite specific question is what general principle would lead you to prefer one over the other?

gnat
  • 20,543
  • 29
  • 115
  • 306

2 Answers2

7

Note: don't use print for logging purposes. Using print may work for small applications, but when the application starts increasing, moving to the actual logging would quickly become unavoidable. To avoid future maintenance cost, consider using logging from the beginning. Make sure you use existent predefined logging frameworks and don't reinvent the wheel.


Is the print statement part of the function? In other words, does it make sense to run the function without the print statement?

If the specific statement is inherent to the function, put it inside. If the specific statement is inherent to the context of the caller, put it there.

Example:

def add_product(product):
    logger.debug("The product %s is about to be added to the database.", product.id)
    ...

Here, the logging is inherent to the function: it doesn't matter when and where the function was called, so whenever it is, the log entry should be added.

def add_product(product):
    ...

logger.debug("Adding the product %s created by the administrator.", product.id)
add_product(self.newProduct)

Here, on the other hand, the context is important: the log message indicates why the product is being added to the database—it is added because the administrator just created it. Thus, the message makes no sense within the function.

2

There is better ways to enable your users to follow the scripts actions. One way is to return an object that describes what steps happend, what the result is and how long the steps took. If it breaks, you should throw an exception which includes additional information.

Another way to do this is using AOP features. These are however not builtin python and you have little IDE support when using reflection/introspection to achieve the desired AOP behaviour. The advantage is, that your logging code and the functional code is seperated and the logging can be enabled and disabled or even extended without having to touch the functional code.

If you want to use neither of these solutions, at least make your users to be able to inject a service that is used for printing, so they can decide what the service should do with your messages. It is really bad if you are using a third-party script and the script just prints to stdout or stderr. You then have to do dirty piping stuff to prevent unwanted output.

valenterry
  • 2,429