Exercise 7.2 - Solution
(a) Adding logging to a module
# fileparse.py
import csv
# Get a logger on which to issue diagnostics. The __name__ variable
# contains the module name--so in this case the logger should have
# the name 'fileparse'
import logging
log = logging.getLogger(__name__)
def parse_csv(filename, select=None, types=None, has_headers=True, delimiter=',', ignore_errors=False):
'''
Parse a CSV file into a list of records with type conversion.
'''
if select and not has_headers:
raise RuntimeError("select requires column headers")
f = open(filename)
f_csv = csv.reader(f, delimiter=delimiter)
# Read the file headers (if any)
headers = next(f_csv) if has_headers else []
# If specific columns have been selected, make indices for filtering and set output columns
if select:
indices = [ headers.index(colname) for colname in select ]
output_columns = select
else:
indices = []
output_columns = headers
records = []
for rowno, row in enumerate(f_csv, 1):
if not row: # Skip rows with no data
continue
# If specific column indices are selected, pick them out
if indices:
row = [ row[index] for index in indices]
# Apply type conversion to the row
if types:
try:
row = [func(val) for func, val in zip(types, row)]
except ValueError as e:
if not ignore_errors:
log.warning("Row %d: Couldn't convert %s", rowno, row)
log.debug("Row %d: Reason %s", rowno, e)
continue
# Make a dictionary or a tuple
if output_columns:
record = dict(zip(output_columns, row))
else:
record = tuple(row)
records.append(record)
f.close()
return records
====(b) Adding Logging to an Application
You simply need to add some logging configuration to your program in the main program.
Due to earlier exercises and practicum projects, your solution might look quite different
than this. However, the key part is the call to logging.basicConfig()
.
# report.py
...
if __name__ == '__main__':
import sys
import logging
if len(sys.argv) != 3:
raise SystemExit('Usage: %s portfile pricefile' % sys.argv[0])
portfile = sys.argv[1]
pricefile = sys.argv[2]
# Config logging
logging.basicConfig(
filename='report.log',
filemode='w',
level=logging.WARNING
)
portfolio_report(portfile, pricefile)
[ Back ]