Python tips and tricks

This is a memo to myself of python things I have found useful to keep at hand.


Profiling the execution of a script

The following command runs the given script and prints out stats of where time was spent during code execution. Extremely useful when performance is important, to figure out where to start.

python -m cProfile -s cumtime script_being_profiled.py

Configuration file

Config file has sections (name in brackets) and params

[config]
param = paramValue

Then from the script:

from ConfigParser import SafeConfigParser

parser = SafeConfigParser()
parser.read('config.ini')

MY_PARAM = parser.get('config', 'param')

Logging to file

Python’s logging facility is very simple to use, and so much better than to sprinkle “print” statements all over the code.

The following boilerplate init code works fine for me:

import logging
import logging.handlers

LOG_LEVEL = logging.INFO  # Could be e.g. "DEBUG" or "WARNING"

# Give the logger a unique name (good practice)
logger = logging.getLogger(__name__)

# Set the log level to LOG_LEVEL
logger.setLevel(LOG_LEVEL)

# Make a handler that writes to a file, making a new file at midnight and keeping 3 backups
#handler = logging.handlers.TimedRotatingFileHandler(LOG_FILENAME, when="midnight", backupCount=3)
# Handler writing to a file, rotating the file every 50MB
handler = logging.handlers.RotatingFileHandler(LOG_FILENAME, maxBytes=50000000)
# Format each log message like this
#formatter = logging.Formatter('%(asctime)s %(message)s')
formatter = logging.Formatter("%(asctime)s %(message)s", "%d/%m %H:%M:%S")

# Attach the formatter to the handler
handler.setFormatter(formatter)
# Attach the handler to the logger
logger.addHandler(handler)

# Make a class we can use to capture stdout and sterr in the log
class MyLogger(object):
	def __init__(self, logger, level):
		"""Needs a logger and a logger level."""
		self.logger = logger
		self.level = level

	def write(self, message):
		# Only log if there is a message (not just a new line)
		if message.rstrip() != "":
			self.logger.log(self.level, message.rstrip())

# Replace stdout with logging to file at INFO level
sys.stdout = MyLogger(logger, logging.INFO)
# Replace stderr with logging to file at ERROR level
sys.stderr = MyLogger(logger, logging.ERROR)

then just use logger.info (or debug, or warning, …) instead of print wherever:

logger.info( '%s:OK' % myString)



blog comments powered by Disqus