Category Archives: Python

Accessing Configurations and Settings in Python

The Problem

When coding in Python, we need a way to store configurations and
settings in a file, then be able to access them in the code. Our
requirements for accessing these settings are:

  • Simple to learn and use — We would like to target novice coders
  • Easy to understand
  • Hierarchical of settings

References

The Options

Currently, there are a few options for accessing configurations files,
some of them are:

  • INI file format
    • ConfigParser module
    • ConfigObj
    • INITools
    • cfgparse
  • Straight Python code, via the import mechanism
  • YAML file format with yaml module
  • HierConfig
  • JSON
  • Vinay Sajip’s config module
  • tconfpy

In the following sections, we are going to discuss the advantages and
disadvantages of some of these.

ConfigParser

Advantages

  • Library comes with Python installation, no need to install it
  • Ability to specify a default section
  • Low learning curve

Disadvantages

  • Not zero learning-curve as with straight Python code method
  • No hierarchical of data: the default data layout is just one layer
    deep: A configuration file consists of one or more sections and each
    section contains one or more settings.

ConfigObj

Advantages

  • Simple to learn: the configuration is a two-dimensional array: one for
    each section, and one for the settings
  • Round-trip: read/write from/to files
  • Many other features

Disadvantages

  • Need installation

INITools

This tool is abandoned, so we only mention here for completeness.

cfgparse

Advantages

  • Round-trip read and write
  • Many features
  • Ability to specify a default section

Disadvantages

  • Need installation
  • Not simple to use
  • Higher learning curve than other INI solutions
  • INI file can without section header, which is non-standard

Straight Python Code

Advantages

  • Natively supported: We don’t need any module to parse
  • Low learning curve: The users do not need to learn another
    configuration file format
  • Versatile: This file format supports all kind of data types: integer,
    string, dictionary, array, …
  • Simple usage: The users only need to make sure that the settings file
    is in the same directory as the script

Disadvantages

  • No “default” mechanism as in INI
  • Cannot merge different settings files into one
  • No simple mechanism for dynamically load configuration files. For
    example, the ability to specify different configuration files from the
    command line

Conclusion

Of these solutions, we prefer the the native, straight Python code for
its simplicity, ease of use, and zero learning curve. In the next posts,
I will discuss the straight python code solution in details.

Advertisements

Determine the Last Day of a Month

The Problem

Given a year and a month, I want to determine the last day of that month. For example, if the year is 2004 and the month is 2, then the last day is 29th because of leap year.

The Solution

Calculating the last day of a month is not hard, but complicated by the leap year. If the year is a leap year, then February’s last day will be 29th instead of the usual 28th. My algorithm to find the last day of the month is simpler than that: take the first day of the next month and count backward by one day. Here is the code.

#!/usr/bin/env python

import datetime

def get_last_day_of_the_month(y, m):
	'''
	Returns an integer representing the last day of the month, given
	a year and a month.
	'''

	# Algorithm: Take the first day of the next month, then count back
	# ward one day, that will be the last day of a given month. The 
	# advantage of this algorithm is we don't have to determine the 
	# leap year.

	m += 1
	if m == 13:
		m = 1
		y += 1

	first_of_next_month = datetime.date(y, m, 1)
	last_of_this_month = first_of_next_month + datetime.timedelta(-1)
	return last_of_this_month.day

Discussion

The code above is easy enough to understand. The datetime.timedelta(-1) on line 22 basically says, “subtract one day.”

Python List Assignment Caveat

The Problem

In Python, the assignment operator (=) assign the reference to the list instead of making copy of it. The following interaction will demonstrate this concept:

>>> original = [1,2,3]
>>> reference = original # assign the reference
>>> reference
[1, 2, 3]
>>> reference.append(4)
>>> reference
[1, 2, 3, 4]
>>> original
[1, 2, 3, 4]
>>>
  • In line 1, we create a new list, original, with three elements.
  • In line 2, we assign this list to a new variable, reference.
  • In line 5, we append a new value to reference.
  • What happens to the original list? Line 8 and 9 might bring shock to those who are new to Python. What happened?

The answer is the assignment in line 2 assigns the reference to the list so both original and reference will now share the same list and that changes made to one will reflect in the other. So, how do we really make copy of the list instead of sharing the reference?

The Solutions

To make a new copy of a list, there are two different approaches: using the list() function and using the sub list mechanism. The following interactive session will demonstrate the list() function:

>>> original = [1,2,3]
>>> copy = list(original)
>>> copy.append(4)
>>> copy
[1, 2, 3, 4]
>>> original
[1, 2, 3]
>>> 

In line 2, we use the list function to create a copy of the original and assign that list to the variable copy. Any action on copy at that point on will not affect the original list (line 6 and 7)

The following interactive session will demonstrate the sub list feature:

>>> original = [1,2,3]
>>> copy = original[:]
>>> copy.append(4)
>>> copy
[1, 2, 3, 4]
>>> original
[1, 2, 3]
>>> 

Discussion

while both methods accomlish the same goal, many argues that the sub list method is faster. However, the list() function wins point for being easier to understand, especially to new comers.