11

I have been using the ConfigParser module to write configuration files for some time. However, a thought recently struck me; why not just use pure Python instead? Take this example configuration file:

[parameters]
# Host
host = stackoverflow.com
port = 22

To read these values into my code, I do

import ConfigParser
config = ConfigParser.SafeConfigParser()
config.read('host.cfg')

host = config.get('parameters', 'host')
port = config.get('parameters', 'port')

On the other hand, if I had a config file like this:

# Host
host = 'stackoverflow.com'
port = 22

In my main code, I could do this:

from host_cfg import *

So what do I gain from using the ConfigParser module? What are the pros and cons of each approach?

mshell_lauren
  • 5,171
  • 4
  • 28
  • 36

3 Answers3

11

So what do I gain from using the ConfigParser module?

Compatibility with Windows .ini files. Makes some people happy.

What are the pros and cons of each approach?

ConfigParser has limited syntax and some relatively simple things get very contrived. Look at logging for examples.

Python syntax is simpler and much easier to work with. There's no security hole, since no one will waste time hacking a config file when they can simply hack your source code. Indeed, they can hack most of the built-in Python library. For that matter, they could cook the Python interpreter itself.

No one wastes time hacking config files when there are much, much easier exploits elsewhere in your application source code.

S.Lott
  • 384,516
  • 81
  • 508
  • 779
6

ConfigParser parses simple, flat configuration data. Importing a python module runs code. For configuration files, you want data, not code. Case closed.

Okay, more detailed: Code can do all kinds of things, including breaking more easily - especially when edited by non-programmers (try explaining .ini modders that they e.g. have to use matched quotes and escape things...) - or cause namespace conflicts with other parts of your application (especially if you import *). Also see the rule of Least Power.

  • @delnan Good explanation, but the last part of your answer sounds like you are ridiculing the the OP for not knowing the answer (although I doubt that's what you meant). I'll vote for your answer with a small edit to its tone. – Steven Rumbalski Nov 17 '10 at 19:44
  • @delnan +1. My comment posted after your edit but referred to the answer before the edit. – Steven Rumbalski Nov 17 '10 at 19:47
  • @Steven: The tone still needed some polish imo. –  Nov 17 '10 at 19:48
  • 1
    -1: "Case closed." Far from true. Running code for configuration simplifies a lot of things. The evil sociopath who might "exploit" your configuration has complete access to all your Python code. Why stop at fudging the config? Why not just adulterate **all** the code? – S.Lott Nov 17 '10 at 19:48
  • @S.Lott: Come again? Yes, if malicous code gets to edit the config file, it might as well change the actual code. But I didn't claim that the OP's proposal is a security vulnerability(discuss that with @kindall). My reasoning is different. –  Nov 17 '10 at 19:50
  • @delnan: try explaining .ini modders that they have to match the []'s on the [name] paragraphs. Syntax is syntax. A Python config that uses a sensible subset of Python is as simple as a config file. No simpler. And no more complex, either. There's potential complexity, but you don't teach an .ini modders all of Python to change a single string value. – S.Lott Nov 17 '10 at 19:54
  • @S.Lott: .ini(-like) syntax is very widespread and most users that dare to edit a configuration file propably know it (not to mention that they would rarely have to touch the section headers). But OTOH, quite a few of them would get tripped by things like the need to quote things. And those who do know can still complain - "Why require friggin' quotes if .ini gets along without?" -- "Because Python grammar says so." -- "*Great* reason..." –  Nov 17 '10 at 19:57
  • @delnan: Why require friggin []'s in the first place when Python doesn't need them? I don't get your point. Ini syntax isn't magically simpler. Why continue to claim that it's simpler? – S.Lott Nov 17 '10 at 21:18
  • @S.Lott: A ini parser *is* much simpler (as in, smaller) as a Python parser, simply because the former is just a very simple data format while the latter is a whole programming language. But that's not the point, and I don't argue that the syntax is "simpler". I just assume that of the people that might edit the config file, many will know ini syntax while few will know Python syntax - correct me if you have evidence that this isn't the case - and that therefore specifying the data in INI format would be easier *for the users*. –  Nov 17 '10 at 21:22
  • 1
    @delnan: I'm not comparing ALL of python to ini. Just assignment of integers and strings. Which seems about as simple as ini files. I'm claiming that .ini syntax is equally obscure. Do you have evidence? I have no reason to believe that people magically know .ini any better than Python assignment statements. I think both syntax are more-or-less equally fraught with problems. That's why the case is not "closed." – S.Lott Nov 17 '10 at 21:25
  • @S.Lott: **I am not arguing that X syntax is in any way technically superior/inferior.** I don't mind anyone disagreeing with me, but please at least answer on what I actually write. And I just write that the **users** (who will edit those files) will propably be more familiar with ini-like syntax. <--- THIS. Reason against this assumption, or this discussion is pointless. –  Nov 17 '10 at 21:30
  • @delnan: "users (who will edit those files) will propably be more familiar with ini-like syntax". False. Users who edit these files are confronted with a variety of syntax. Apache's weird notation. Java config files. Python and INI are **equally** confusing to them. The case is not "closed". This is my point. The case is not "closed". Not "closed". Open to some possibility that there's a chance that .INI is not magically better but just as bad as all others. – S.Lott Nov 17 '10 at 22:00
4

A potential "con" of the Python file approach is that your user can put arbitrary code in the file that will be executed in your application's context. As S. Lott points out in the comments to this answer (when I was somewhat more forceful in my warning), this is usually not an issue because the user (or a hacker) will usually have access to your entire source code anyway and can make any desired changes.

However, I can certainly imagine situations in which the approach could result in a new security hole, such as when the main script files are writable only by the system administrator and the per-user config file is the only file editable by the end user. Unless you are certain that your code will never run in such an environment, I would not recommend the Python module approach. There are good reasons that "don't execute code given to you by users" is widely considered a best practice.

Executing the config file also makes handling errors problematic. If the user introduces a syntax error, you will want to trap it, and you can do so easily by throwing a try around your import, but nothing after the error will be executed. In a config file, usually parsing will continue with the next line, so the user will miss at most one setting instead of (say) half of them. There are ways to make a Python module work more like a config file (you could read the file as text and exec() each line, for example) but if you have to do any work at all, it becomes easier to use ConfigParser.

If, despite all this, you still want to use Python syntax in your config file, you could use the ast module (see function literal_eval()).

kindall
  • 178,883
  • 35
  • 278
  • 309
  • 2
    -1: "your user can put arbitrary code in the file that will be executed in your application's context". A silly consideration. The user has all of the Python code available. They can hack any of the Python code they want to hack. The config file is not actually a useful target when logging passwords being hashed by `hashlib` is so much simpler. – S.Lott Nov 17 '10 at 19:50
  • I was rather assuming that if you were going to distribute a Python app you'd wrap it using py2exe or a similar tool, making the original source files somewhat less accessible. However, your point is taken. – kindall Nov 17 '10 at 20:06
  • 1
    @kindall: "user will miss at most one setting instead" How is this good? This could be fatally bad, indeed, it could lead to horrifying security breaches or worse. I'd rather have Nothing work if the config is wrong than have some partial config do something horrifyingly wrong. I can't believe you'd tout this as an "advantage". Partial configuration is very a serious problem. – S.Lott Nov 18 '10 at 01:14
  • Depends on the situation. I might prefer to get as much as I can and try to provide safe defaults for missing values based on what I could read, or give specific messages about what is missing when I can't do that. I can see ways to do that with the module approach, but it seems like it would be more work that way, and involve some reinvention of wheels. – kindall Nov 18 '10 at 03:58
  • 1
    @kindall: "safe defaults" is never an appropriate response to a syntax error. The syntax error might be in the most important parameter, the one that overrides settings from no security to real security. Missing that one parameter -- due to a syntax error -- is unthinkable. Bad syntax in parameters means the application cannot (and should not) start running in a compromised mode using "safe" defaults. It should refuse to run -- i.e., crash. That's the only sensible response and .ini files are not better (nor any worse) than other formats. – S.Lott Nov 18 '10 at 04:13
  • I see the Microsoft tradition of crashing when a trivial setting can't be read is alive and well. ;-) Not all settings are equally important, and the programmer may use his intelligence and judgment in deciding what to do if one can't be read. I agree that the actual format is not important; the fact that there exists a well-designed, feature-rich, tested, documented standard library for a particular format for `.ini` files is nice, though. I suppose you could use XML, but ConfigParser has some nice features specifically for the config-file use case and is probably lighter in weight than DOM. – kindall Nov 18 '10 at 15:27