Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Jul 11th, 2006, 7:33 PM   #1
titaniumdecoy
Expert Programmer
 
titaniumdecoy's Avatar
 
Join Date: Nov 2005
Posts: 908
Rep Power: 3 titaniumdecoy is on a distinguished road
Send a message via AIM to titaniumdecoy
Storing preferences

I want to store my script's preferences in a file that is human-readable and -editable. Is there a standard Python class for storing and parsing a file in the format VARIABLE=VALUE on each line? I know I can write my own function to do this very easily but since Python seems to have built-in classes for just about everything I thought I'd ask. Thanks.
titaniumdecoy is offline   Reply With Quote
Old Jul 11th, 2006, 7:35 PM   #2
Sane
Programming Guru
 
Sane's Avatar
 
Join Date: Apr 2005
Location: Waterloo, Ontario
Posts: 2,031
Rep Power: 6 Sane will become famous soon enough
Send a message via MSN to Sane
Well, it's a little dangerous. But you can actually just straight out execute the configuration file.

exec open('options.conf', 'r').read()

But, it's dangerous. And slow.
Sane is online now   Reply With Quote
Old Jul 11th, 2006, 7:47 PM   #3
Cerulean
Professional Programmer
 
Cerulean's Avatar
 
Join Date: Apr 2005
Location: London, England
Posts: 459
Rep Power: 4 Cerulean is on a distinguished road
Quote:
Originally Posted by Sane
But, it's dangerous. And slow.
I don't know if i'd call it dangerous. I'd say that it's nice having the ability to tap into a fully blown programming language when doing your config. I use Python for some of my configurations and it works just fine.
As for slow, I'd imagine that loading Python is way faster than reading in XML via Python or parsing stuff yourself.
Also, if your config file is just named config.py, you can just import it without having to manually open and read and exec it.
import config
print config.foo
Now what would be harder would be to write Python code back out into the file (say you changed the config programatically from your application).
When I want simple key=value, newline seperated config options, I just do something like this:
def readConfig(fname):
    data = file(fname).read()
    return dict([x.split("=") for x in data.split("\n")])

def writeConfig(config, fname):
    f = file(fname, "w")
    f.write("\n".join(["=".join(item) for item in config.items()]))
    f.close()
Obviously you could abstract this way into a Configuration class or some such that behaves like a dictionary but handles syncing for you automagically.
Cerulean is offline   Reply With Quote
Old Jul 11th, 2006, 7:49 PM   #4
Arevos
Programming Guru
 
Arevos's Avatar
 
Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5 Arevos is on a distinguished road
Take a look at ConfigParser.

If you had a configuration file called test.cfg:
[defaults]
host = localhost
port = 80

Then you could access it thus:
>>> from ConfigParser import ConfigParser
>>> config = ConfigParser()
>>> config.read("test.cfg")
["test.cfg"]
>>> config.sections()
['defaults']
>>> config.options("defaults")
['host', 'port']
>>> config.get("defaults", "host")
'localhost'
>>> config.get("defaults", "port")
'80'

Last edited by Arevos; Jul 11th, 2006 at 8:10 PM.
Arevos is offline   Reply With Quote
Old Jul 11th, 2006, 7:57 PM   #5
titaniumdecoy
Expert Programmer
 
titaniumdecoy's Avatar
 
Join Date: Nov 2005
Posts: 908
Rep Power: 3 titaniumdecoy is on a distinguished road
Send a message via AIM to titaniumdecoy
Does ConfigParser support comments, eg lines beginning with #?

What I am trying to do is read and set each variable AND value from the config file. At the moment I don't know the names of the variables, which I was asking about in this thread. This probably isn't possible with ConfigParser.
titaniumdecoy is offline   Reply With Quote
Old Jul 11th, 2006, 8:11 PM   #6
Sane
Programming Guru
 
Sane's Avatar
 
Join Date: Apr 2005
Location: Waterloo, Ontario
Posts: 2,031
Rep Power: 6 Sane will become famous soon enough
Send a message via MSN to Sane
I was bored so I made this silly little class.

It gets the job done, and it's safe from any stupid stunts the user tries to pull.


class conf:
    def __init__(self, filename):
        self.CONF_FILE = filename

    def save(self, opts):

        data = '\n'.join(['%s = %s'%(key, opts[key]) for key in opts])

        stream = open(self.CONF_FILE, 'w')
        stream.write(data)
        stream.close()

    def load(self):

        stream = open(self.CONF_FILE, 'r')
        data = stream.read().split('\n') # readlines keeps the \n there, I don't like that
        stream.close()

        opts = dict()

        for line in data:
            newline = line.split('=', 1)

            if len(newline) < 2:
                raise Exception, 'A line without an equal sign was found'

            lennewline0 = len(newline[0])

            for char in range(lennewline0):
                if newline[0][lennewline0-char-1] != ' ':
                    key = newline[0][:lennewline0-char]
                    break

            for char in range(len(newline[1])):
                if newline[1][char] != ' ':
                    value = newline[1][char:]
                    break

            try:
                newvalue = int(value)

            except ValueError:
                newvalue = value

            opts[key] = newvalue

        return opts
                

if __name__ == '__main__':
            
    data = conf('options.conf')

    data.save( {'level' : 4,
                'volume' : 9,
                'graphics' : 'high',
                'event' : 4112 } )

    options = data.load()

    print options['event']

With some simple modifications, you could make it so it sets actual variables in an object using "setattr". That's if you would rather not have a dictionary of values.
Sane is online now   Reply With Quote
Old Jul 11th, 2006, 8:14 PM   #7
Arevos
Programming Guru
 
Arevos's Avatar
 
Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5 Arevos is on a distinguished road
Quote:
Originally Posted by titaniumdecoy
Does ConfigParser support comments, eg lines beginning with #?
From the ConfigParser documentation:
Quote:
Lines beginning with "#" or ";" are ignored and may be used to provide comments.
Quote:
Originally Posted by titaniumdecoy
This probably isn't possible with ConfigParser.
Again, from the ConfigParser documentation:
Quote:
write(fileobject)
Write a representation of the configuration to the specified file object. This representation can be parsed by a future read() call. New in version 1.6.
Arevos is offline   Reply With Quote
Old Jul 11th, 2006, 8:21 PM   #8
titaniumdecoy
Expert Programmer
 
titaniumdecoy's Avatar
 
Join Date: Nov 2005
Posts: 908
Rep Power: 3 titaniumdecoy is on a distinguished road
Send a message via AIM to titaniumdecoy
Thanks Arevos and Sane, but ConfigParser seems a little too complicated, and I wanted to be able to represent tuples of values by items separated with commas; previously read variables as values prepended with $; comments; and more. So I wrote my own little class:

import gimmie

prefsfile = r'C:\Documents and Settings\jboyle\Desktop\python_scripts\OLD\nightcrawler_prefs.txt'

prefs = {}

def readprefs(prefsfile, cls):
    """Read constants from prefsfile into new variables in cls"""
    for line in prefsfile:
        line = line.strip()
        # Process line if it is not empty or a comment
        if len(line) > 0 and not line.startswith('#'):
            var, values = line.split('=')
            values = values.split(',')
            
            # Replace $VALUE with corresponding value
            values = fillvalues(values, cls)
            
            # Return value or tuple of values
            if len(values) == 1: setattr(cls, var, values[0])
            else: setattr(cls, var, tuple(values))

def fillvalues(vals, cls):
    """Replace each $VALUE in vals with corresponding value in cls"""
    temp_vals = list(vals)
    for i, v in enumerate(temp_vals):
        if v.startswith('$') and hasattr(cls, v.strip('$')):
            w = getattr(cls, v.strip('$'))
            # If w is a single-element tuple, extract the element
            if type(w) is tuple and len(w) == 1: w = w[0]
            vals[i] = w
    return vals

def readfile(prefsfile, method, cls):
    """Read each line in file and pass it to method along with cls"""
    try:
        file = open(prefsfile)
        try:
            method(file, cls)
        finally:
            file.close()
    except IOError:
        print 'There was an error reading the NightCrawler prefs file',
        print '[%s]' % prefsfile

readfile(prefsfile, readprefs, gimmie)
titaniumdecoy is offline   Reply With Quote
Old Jul 11th, 2006, 8:26 PM   #9
Sane
Programming Guru
 
Sane's Avatar
 
Join Date: Apr 2005
Location: Waterloo, Ontario
Posts: 2,031
Rep Power: 6 Sane will become famous soon enough
Send a message via MSN to Sane
By the way, for clarifaction, that is not a class. >_>;;

A class is... basically what my code demonstrates. You can create an instance of a class with an object, and call functions of the class as methods. Containing all the individual variables within each individual instance of the class.
Sane is online now   Reply With Quote
Old Jul 11th, 2006, 8:29 PM   #10
titaniumdecoy
Expert Programmer
 
titaniumdecoy's Avatar
 
Join Date: Nov 2005
Posts: 908
Rep Power: 3 titaniumdecoy is on a distinguished road
Send a message via AIM to titaniumdecoy
I know what a class is. I get lazy sometimes. :mad:

Although, having thought further on the matter, the script I wrote doesn't address saving new values. That is a problem. A very big one.

I may have to go back and look at ConfigParser.

In fact, having a human-readable file is more problematic than I thought. I may go back to just using the shelve module.
titaniumdecoy is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Storing Data crawforddavid2006 C++ 11 Jun 24th, 2006 1:41 PM
Storing passed information into a text file dunowhodoyou PHP 9 May 8th, 2006 11:29 AM
Storing variables to a file? Oddball PHP 2 Mar 21st, 2006 3:09 PM
Storing Negative Numbers in unsigned ints aznluvsmc C 9 Aug 22nd, 2005 11:09 PM
Language preferences peace_of_mind Coder's Corner Lounge 7 Apr 1st, 2005 1:52 PM




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 7:34 PM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC