Reputation: 45
I have a file in which my data is like:
1 [0,1, 4, 89]
2 [3, 56, 6]
3 [3,4,0]
And so on.
I'd like to read this file to access data line by line in my script so I try this to read my file and memorize it in a dictionary:
dictionary = {}
with open('file.txt') as f:
for line in f:
nb, list = line.split(' ')
dictionary[nb] = list
Then I will do something like:
for e in dictionary:
etc.
I have this error:
too many values to unpack
because I don't know how to deal with the second split element which is a list.
Is there an other way to access and work with any input file easily?
Upvotes: 1
Views: 3914
Reputation: 49318
Use the maxsplit
argument and ast.literal_eval()
:
import ast
dictionary = {}
with open('file.txt') as f:
for line in f:
nb, l = line.split(maxsplit=1)
dictionary[nb] = ast.literal_eval(l)
Note that I've changed the name of the list
to something that doesn't mask the built-in function list()
, and used the default delimiter of any whitespace.
Upvotes: 1
Reputation: 11590
Would this do?
import ast
d = dict()
with open('file.txt') as f:
for line in f:
k, l = line.split(' ', 1)
d[k] = ast.literal_eval(l)
print(d)
it produces
{'3': [3, 4, 0], '1': [0, 1, 4, 89], '2': [3, 56, 6]}
In case you want the key to be an integer instead of a string just do
d[int(k)] = ast.literal_eval(l)
Upvotes: 1
Reputation: 22282
First at all, you can set a maxsplit
argument of str.split()
. From the document:
str.split(sep=None, maxsplit=-1)
Return a list of the words in the string, using sep as the delimiter string. If maxsplit is given, at most maxsplit splits are done (thus, the list will have at most
maxsplit+1
elements). If maxsplit is not specified or-1
, then there is no limit on the number of splits (all possible splits are made).
Demo:
>>> s = '1 [0,1, 4, 89]'
>>> s.split(' ', 1)
['1', '[0,1, 4, 89]']
>>> s.split(' ')
['1', '[0,1,', '4,', '89]']
>>> s.split(' ')[1]
'[0,1,'
>>> s.split(' ', 1)[1]
'[0,1, 4, 89]'
Then you need convert the string of list to a real list. I'd recommend use ast.literal_eval()
. From the document:
ast.literal_eval(node_or_string)
Safely evaluate an expression node or a string containing a Python literal or container display. The string or node provided may only consist of the following Python literal structures: strings, bytes, numbers, tuples, lists, dicts, sets, booleans, and
None
.
For example:
>>> import ast
>>> s = '1 [0,1, 4, 89]'
>>> s.split(' ', 1)[1]
'[0,1, 4, 89]'
>>> ast.literal_eval(s.split(' ', 1)[1])
[0, 1, 4, 89]
>>> type(ast.literal_eval(s.split(' ', 1)[1]))
<class 'list'>
>>> type(s.split(' ', 1)[1])
<class 'str'>
If you need remove the \n
after the string, just use str.strip()
. From the document:
str.strip([chars])
Return a copy of the string with the leading and trailing characters removed. The chars argument is a string specifying the set of characters to be removed. If omitted or None, the chars argument defaults to removing whitespace.
Use it like this:
>>> ' 1 [0,1, 4, 89] '.strip()
'1 [0,1, 4, 89]'
>>> '1 [0,1, 4, 89]\n'.strip()
'1 [0,1, 4, 89]'
>>>
It remove all tabs, newlines, spaces before and after the string, If you just want remove the spaces, newlines before or after the string, take a look at str.lstrip()
and str.rstrip()
.
So you can write your code like this:
import ast
dictionary = {}
with open('file.txt') as f:
for line in f:
key, value = line.strip().split(1)
dictionary[key] = value
If you want the dictionary
's keys be int objects, just use int()
function to convert it like:
import ast
dictionary = {}
with open('file.txt') as f:
for line in f:
key, value = line.strip().split(' ', 1)
dictionary[int(key)] = value
Upvotes: 3
Reputation: 85442
For a save eval use ast.literal_eval:
from ast import literal_eval
data = {}
with open('file.txt') as fobj:
for line in fobj:
key, rest = line.split(None, 1)
data[key] = literal_eval(rest)
>>> data
{'1': [0, 1, 4, 89], '2': [3, 56, 6], '3': [3, 4, 0]}
From the docs:
ast.literal_eval(node_or_string)
This can be used for safely evaluating strings containing Python values from untrusted sources without the need to parse the values oneself.
Upvotes: 1