TAGS :Viewed: 6 - Published at: a few seconds ago

[ Convert commented out print statements to logging calls - Python ]

I'm hacking on a framwork right now, and I'd like to use logging. However, the developers of the framework have been using print statements to debug, and they are all commented out for the production release. I was wondering, does anyone know of a regex to find these, and convert them to logging calls.

This is what I was thinking so far:

import re
import sys
import StringIO

if not len(sys.argv) != 2:
    print 'Syntax: printtologging.py file_to_process'

regex = r'#print (?P<debugstring>*)$'

output = StringIO.StringIO('w+')

def replace(match_object):
    return 'logging.debug({0})'.format(match_object.group_dict['debugstring'])

with open(sys.argv[1]) as f:
    output.writelines([re.sub(regex, replace, line) for line in f.readlines()])

print output.read()

Though that dosn't seem to be working. My regex's are far from brilliant, could anyone help?

Answer 1

If you want to do it in Python, consider using the fileinput module:

import fileinput
import sys
import re

def convert(paths):
    for line in fileinput.input(paths, inplace=True, backup='~'):

if __name__=='__main__':

You could call the script this way

% print2log.py *.py

It converts the scripts in-place, and makes a backup file which ends with ~.

Note that the regex converts

#print 'foo'   -->  logging.debug('foo')

but adds an extra set of parentheses if the print statement already had one:

#print('foo')  --> logging.debug(('foo'))

It also screws up multi-line print statements:

#print('''foo        logging.debug(('''foo)
#bar''')       -->   #bar''')

Fixing this is a much harder problem, requiring parsing the comments and using something smarter than regex, which can't handle nested parentheses properly. I think you could do it with tokenize, and with code similar in spirit to reindent.py, but it would take some time and thought to get it right.

Answer 2

If all the print statements are already contained in brackets, then sed will do the job:

sed -i s/#print/logging\.debug/g files_to_process

Answer 3

You can achieve the same with sed

sed -i.old -E -e "s/#+[[:space:]]*print (.*)/logging.debug(\1)/" FILE

I made your regex a bit more robust. It now also matches if multiple # and/or whitespace between # and print are present.

Note that it still doesn't handle some edge cases like

#print 'foo'; print'bar'

-i.old activates in-place editing with a backup written to FILE.old. Omit the .old if you don't want backups, i.e. sed -i -E ...

Answer 4

An alternative to this is to leave the print statements in place and to replace sys.stdout with a file like object that does logging.