Reputation: 9708
I am getting various data types from a config file and adding them to a dictionary. but I am having a problem with lists. I want to take a line with text: alist = [1,2,3,4,5,6,7]
and convert into a list of integers. But I am getting
['1', ',', '2', ',', '3', ',', '4', ',', '5', ',', '6', ',', '7'].
How can I fix this?
Here is config.txt:
firstname="Joe"
lastname="Bloggs"
employeeId=715
type="ios"
push-token="12345"
time-stamp="Mon, 22 Jul 2013 18:45:58 GMT"
api-version="1"
phone="1010"
level=7
mylist=[1,2,3,4,5,6,7]
Here is my code to parse:
mapper = {}
def massage_type(s):
if s.startswith('"'):
return s[1:-1]
elif s.startswith('['):
return list(s[1:-1]) #in this case get 'mylist': ['1', ',', '2', ',', '3', ',', '4', ',', '5', ',', '6', ',', '7']
elif s.startswith('{'):
return "object" #todo
else:
return int(s)
doc = open('config.txt')
for line in doc:
line = line.strip()
tokens = line.split('=')
if len(tokens) == 2:
formatted = massage_type(tokens[1])
mapper[tokens[0]] = formatted
#check integer list
mapper["properlist"] = [1,2,3,4,5,6,7] #this one works
print mapper
Here is my printed output:
{'time-stamp': 'Mon, 22 Jul 2013 18:45:58 GMT', 'mylist': ['1', ',', '2', ',', '3', ',', '4', ',', '5', ',', '6', ',', '7'], 'employeeId': 715, 'firstname': 'Joe', 'level': 7, 'properlist': [1, 2, 3, 4, 5, 6, 7], 'lastname': 'Bloggs', 'phone': '1010', 'push-token': '12345', 'api-version': '1', 'type': 'ios'}
Update.
Thanks for the feedback. I realised that I could also get heterogeneous list so changed list part to:
elif s.startswith('['):
#check element type
elements = s[1:-1].split(',')
tmplist = [] #assemble temp list
for elem in elements:
if elem.startswith('"'):
tmplist.append(elem[1:-1])
else:
tmplist.append(int(elem))
return tmplist
It only handles strings and integers but is good enough for what I need right now.
Upvotes: 2
Views: 160
Reputation: 8581
I like the idea of using ConfigParser as @erewok mentioned, here's the whole "parser"
def parse(content):
def parseList(content):
# Recursive strategy
listed = content.strip("[]").split(",")
return map(parse, listed)
def parseString(content):
return content.strip("\"")
def parseNumber(content):
return int(content)
def parse(content):
if (content.startswith("\"")):
return parseString(content)
elif (content.startswith("[")):
return parseList(content)
elif (content.isdigit()):
return parseNumber(content)
# Create dictionary with values
result = {}
for line in content.splitlines():
key, value = line.split("=",1)
result[key] = parse(value)
return result
I'm using a recursive strategy to sub-parse elements within the list you are getting, in case the list comes with numbers and strings mixed
Upvotes: 0
Reputation: 7845
You might also consider using ConfigParser (Python 3 example below, Python 2 imports ConfigParser.ConfigParser
, I believe):
from configparser import ConfigParser
parser = ConfigParser()
conf_file = os.path.join(dir_it's_located_in, 'config.txt')
parser.read(conf_file)
After that, it's really basic: your whole config file is treated like a dictionary object and all configuration lines are keys in the dictionary:
firstname = parser['firstname']
lastname = parser['lastname']
You can also set up sections in your configuration like so:
[employee info]
email = "[email protected]"
birthday = 10/12/98
And you can reference these in the following way:
birthday = parser["employee info"]["birthday"]
And, as always, there are some great examples in the docs: http://docs.python.org/3.2/library/configparser.html
Upvotes: 1
Reputation: 1163
Currently you're converting a string to a list of characters. You want to be doing this:
map(int, str[1:-1].split(','))
That will give you the list of ints you are after.
Upvotes: 0
Reputation: 114098
ummm
elif s.startswith('['):
return map(int,s[1:-1].split(","))
Upvotes: 0
Reputation: 8043
maybe try ast.literal_eval
here is an example:
import ast
str1 = '[1,2,3,4,5]'
ast.literal_eval(str1)
output will be a list like this:
[1,2,3,4,5]
it wont include the commas in the list
Upvotes: 2
Reputation: 34531
You need to change the return
statement to.
return [int(elem) for elem in s[1:-1].split(',')] # Or map(int, s[1:-1].split(','))
Upvotes: 2
Reputation: 27812
You can use split()
:
elif s.startswith('['):
return [int(x) for x in s[1:-1].split(',')]
This will give you the list without the commas.
Upvotes: 0