6. Common tasks
6.1. Configuration files
6.1.1. In Perl
What we're trying to accomplish ist the Python equivalent of
%config={}; open(CFG,"testfile.txt"); while (<CFG>){ s/#.*//; if (/(\w+)=(.*)/){ $config{$1}=$2; print "config{$1}=$2; $config{$1}\n"; } }
So, a simple configuration file, with comments and simple a=b assignments.
While reding, we also want some sanity-checks, whitch is done by the matching
of the regular expressions. The result should be some form of hash/dictionary
in which we can lookup the values by text.
6.1.2. configobj
The Python-way seems to be to google if there is a module that does it
for you and then use that module. There are a number of modules that read
config files, and configobj seems the most simple one.
If it would work.
Try 1:
import configobj config=configobj.configobj("testfile.txt")
Result:
Traceback (most recent call last): File "configobj.py", line 2, in <module> import configobj File "/home/ljm/src/learning_python/configobj.py", line 3, in <module> config=configobj.configobj("testfile.txt") TypeError: 'module' object is not callable
The type of
configobj.configobj
is a module. That is a bit unexpected. Especially since many answers on the Internet
suggest that
configobj
is the module and
configobj.configobj
should be the way to use it. But apparently, it is not.
import configobj print type(configobj) print type(configobj.configobj) print type(configobj.configobj.configobj)
gives:
<type 'module'> <type 'module'> <type 'module'> <type 'module'> <type 'module'> <type 'module'>
Try 2:
from configobj import configobj
which gives:
Traceback (most recent call last): File "configobj.py", line 2, in <module> from configobj import configobj File "/home/ljm/src/learning_python/configobj.py", line 2, in <module> from configobj import configobj ImportError: cannot import name configobj
Camel-humping the config obj results in yet another import error:
Traceback (most recent call last): File "configobj.py", line 2, in <module> from configobj import ConfiGobj File "/home/ljm/src/learning_python/configobj.py", line 2, in <module> from configobj import ConfiGobj ImportError: cannot import name ConfiGobj
This also means that none of the
configobj examples work. And because I don't understand what is happening
(behavior does not comply with any of the solutions that I got), I will abandon
this module.
6.1.3. ConfigParser
Another module that does the configuration is ConfigParser. It requires a
more complicates configuration file.
import ConfigParser config = ConfigParser.RawConfigParser() config.read('testfile.txt') a=config.get('notes',"do") print a
You must have a
[section header]
in the file, otherwise the module will fail.
Traceback (most recent call last): File "configparser.py", line 4, in <module> config.read('testfile.txt') File "/usr/lib64/python2.7/ConfigParser.py", line 305, in read self._read(fp, filename) File "/usr/lib64/python2.7/ConfigParser.py", line 512, in _read raise MissingSectionHeaderError(fpname, lineno, line) ConfigParser.MissingSectionHeaderError: File contains no section headers. file: testfile.txt, line: 1
eventhough the module is documented (
https://docs.python.org/2/library/configparser.html
), there is still a lot unclear about its
workings. Ah well, that also seems to be the Python way.
6.1.4. Import
There are some that suggest that using
import
and creating valid python code as config file is a good idea.
It is not.
Ofcourse, if everything is completely under control, and your users
won't put code in the config file, then it may not be so bad. But if
your user is anyone else but yourself, don't do this.
6.2. Command line arguments
6.2.1. Sys.argv
If you want to interact with anything beyond the most simplset, you need to import
sys.
In
sys
there is an array
sys.argv
that contains the arguments. Like everywhere else,
sys.argv[0]
contains the name of the script or program.
6.2.2. Getopt
A more or less standard way of parsing arguments is getopt. This
is available in C, Perl, Bashe and many others, and also in
Python. However, because it is standard, Python doesn't like it. The
official stance is that getopt is not deprecated, but argparse is more
actively maintained and should be used for new development.
The following sniplet shows the use of getopt:
#!/usr/bin/python import sys, getopt try: opts, args = getopt.gnu_getopt(sys.argv[1:],"he:q:",["question=","exclamation="]) except getopt.GetoptError: print sys.argv[0], '[-e excalamation ] [ -q question ]' sys.exit(2) for opt, arg in opts: if opt == '-h': print sys.argv[0], '[-e excalamation ] [ -q question ]' sys.exit() elif opt in ("-q", "--question"): print arg,'?' elif opt in ("-e", "--exclamation"): print arg,'!' print 'arg=',args
Note that
getopt.gnu_getopt
gets
sys.argv[1:]
as list of options.
sys.argv[0]
contains the name of the script and would therefore mess-up the
argument parsing.
We used
gnu_getopt
because otherwise, parsing of the flags stops when the first non-flag
argument is encoutered.
The result is shown below.
$ python getops.py -q question answer --exclamation yes oh question ? yes ! arg= ['answer', 'oh']
6.2.3. agparse
Agparse is at the moment the prefered option to parse command line arguments.
It is more advanced than getops, and it has a nice self-documenting feature.
6.3. Regular expression matching
If there's anything Perl is good in, it is handling regular expressions.
In Python, this is made complicated. As if the goal is to discourage the use.
First: it is not standard in Python.
It is an add-on that needs to be imported.