Configuration file use cases

There are two configuration file use cases. Sometimes, we can stretch the definition slightly to add a third use case. The first two should be pretty clear:

  • A person needs to edit a configuration file
  • A piece of software will read a configuration file and make use of the options and arguments to tailor its behavior

Configuration files are rarely the primary input of an application program. Generally, they only tailor the program's behavior. For example, a web server's configuration file might tailor the behavior of the server, but the web requests are one primary input, and the database or filesystem is the other primary input. In the case of a GUI application, the user's interactive events are one input, and the files or database may be another input; a configuration file may fine-tune the application. The most notable exception to this general pattern is a simulation application; in this case, the configuration parameters might be the primary input. 

There's also a blurry edge to the distinction between the application program and configuration input. Ideally, an application has one behavior irrespective of the configuration details. Pragmatically, however, the configuration might introduce additional strategies or states to an existing application, changing its behavior in fundamental ways. In this case, the configuration parameters become part of the code, not merely options or limits applied to a fixed code base.

In addition to being changed by a person, another use case for a configuration file is to save an application's current state. For example, in GUI applications, it's common to save the locations and sizes of various windows. As another example, a web interface often uses cookies to save the transaction state. It's generally helpful to segregate slowly-changing user-oriented configuration from the more dynamic attributes of the application's current operating state. The same types of file formats can be used, but the two kinds of uses are distinct.

A configuration file can provide a number of domains of arguments and parameter values to an application. We need to explore some of these various kinds of data in more detail in order to decide how to represent them best. Some common types of parameters are listed as follows:

  • Device names, which may overlap with the filesystem's location
  • Filesystem locations and search paths
  • Limits and boundaries
  • Message templates and data format specifications
  • Message text, possibly translated for internationalization
  • Network names, addresses, and port numbers
  • Optional behaviors, which are sometimes called feature toggles
  • Security keys, tokens, usernames, and passwords

These values come from a number of distinct domains. Often, the configuration values have relatively common representations using strings, integers, and floating-point numbers. The intent is to use a tidy textual representation that's relatively easy for a person to edit. This means our Python applications must parse the human-oriented input.

In some cases, we may have lists of values where separators are required. We may also have large, multiline blocks of text. In these cases, the representation of the values may involve more complex punctuation and more complex parsing algorithms.

There is one additional configuration value that isn't a simple type with a tidy text representation. We could add this bullet to the preceding list:

  • Additional features, plugins, and extensions; in effect, additional code

This kind of configuration value is challenging. We're not necessarily providing a simple string input or numeric limitation. In fact, we're providing the code to extend the application. When the plugin is in Python code, one option is to provide the path to an installed Python module as it would be used in an import statement using this dotted name: package.module.object. An application can then perform a variation of from package.module import object and use the given class or function as part of the application.

For a configuration that introduces non-Python code as part of a plugin or extension, we have two other techniques to make the external code usable:

  • For binaries that aren't proper executable programs, we can try using the ctypes module to call defined API methods
  • For binaries that are executable programs, the subprocess module gives us ways to execute them

Both of these techniques are beyond the scope of this book. This chapter will focus on the core issue of getting the arguments or the parameter values, which are conventional Python values.

Representation, persistence, state, and usability are discussed in the next section.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset