9

I have a problem. My program is using config file to set options, and one of those options is a tuple. Here's what i mean:

[common]
logfile=log.txt
db_host=localhost
db_user=root
db_pass=password
folder[1]=/home/scorpil
folder[2]=/media/sda5/
folder[3]=/media/sdb5/

etc... Can i parse this into tuple with ConfigParser module in Python? Is there some easy way to do this?

7 Answers 7

14

if you can change config format like this:

folder = /home/scorpil
         /media/sda5/
         /media/sdb5/

then in python:

config.get("common", "folder").split("\n")
Sign up to request clarification or add additional context in comments.

Comments

6

Your config could be:

[common]
logfile=log.txt
db_host=localhost
db_user=root
db_pass=password
folder = ("/home/scorpil", "/media/sda5/", "/media/sdb5/")

Assuming that you have config in a file named foo.cfg, you can do the following:

import ConfigParser
cp = ConfigParser.ConfigParser()
cp.read("foo.cfg")
folder = eval(cp.get("common", "folder"), {}, {})

print folder
print type(folder)

which should produce:

('/home/scorpil', '/media/sda5/', '/media/sdb5/')
<type 'tuple'>

-- EDIT -- I've since changed my mind about this, and would take the position today that using eval in this context is a bad idea. Even with a restricted environment, if the configuration file is under user control it may be a very bad idea. Today I'd probably recommend doing something interesting with split to avoid malicious code execution.

2 Comments

I would agree that in general eval() is not good. In the case where you control the input, and restrict the execution environment it is an acceptable solution.
Evil no, gobsmackingly dangerous yes. The key to safer use of eval() is to ensure that you have specified the global and local parameters to eval(). See docs.python.org/2/library/functions.html#eval for more details.
4

Create configuration:

folders = ['/home/scorpil', '/media/sda5/', '/media/sdb5/']
config.set('common', 'folders', json.dumps(folders))

Load configuration:

tuple(json.loads(config.get('common', 'folders')))

Comments

3

You can get the items list and use a list comprehension to create a list of all the items which name starts with a defined prefix, in your case folder

folders = tuple([ item[1] for item in configparser.items() if item[0].startswith("folder")])

3 Comments

This solution assumes that the entries in the file are in the proper order.
@Terrel Shumway is does but you could always sort the items beforehand.
sorting beforehand won't help: folder[10] < folder[2]
1

I don't know ConfigParser, but you can easily read it into a list (perhaps using .append()) and then do myTuple = tuple(myList)

Comments

1
#!/usr/bin/env python
sample = """
[common]
logfile=log.txt
db_host=localhost
db_user=root
db_pass=password
folder[1]=/home/scorpil
folder[2]=/media/sda5/
folder[3]=/media/sdb5/
"""
from cStringIO import StringIO
import ConfigParser
import re
FOLDER_MATCH = re.compile(r"folder\[(\d+)\]$").match

def read_list(items,pmatch=FOLDER_MATCH):
    if not hasattr(pmatch,"__call__"):
        pmatch = re.compile(pmatch).match
    folder_list = []
    for k,v in items:
        m = pmatch(k)
        if m:
            folder_list.append((int(m.group(1)),v))
    return tuple( kv[1] for kv in sorted(folder_list) )


if __name__ == '__main__':
    cp = ConfigParser.SafeConfigParser()
    cp.readfp(StringIO(sample),"sample")

    print read_list(cp.items("common"))

Comments

1

You could stick to json completely

tst.json

{
  "common": {
    "logfile":"log.txt",
    "db_host":"localhost",
    "db_user":"root",
    "db_pass":"password",
    "folder": [
      "/home/scorpil",
      "/media/sda5/",
      "/media/sdb5/"
    ]
  }
}

then work with it

$ python3

>>> import json
>>> with open("tst.json", "r", encoding="utf8") as file_object:
...   job = json.load(file_object)
... 
>>> job
{'common': {'db_pass': 'password', 'logfile': 
'log.txt', 'db_user': 'root', 'folder': 
['/home/scorpil', '/media/sda5/', '/media/sdb5/'], 
'db_host': 'localhost'}}

>>> print (job["common"]["folder"][0])
/home/scorpil
>>> print (job["common"]["folder"][1])
/media/sda5/
print (job["common"]["folder"][2])
/media/sdb5/

>>> folder_tuple = tuple(job["common"]["folder"])
>>> folder_tuple
('/home/scorpil', '/media/sda5/', '/media/sdb5/')

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.