Reputation: 57
I have a problem. I had a list consisting of namedtuples. I wrote this list to a file.txt. Now i want to read it back. I found out here that json is recommended for converting it beforehand and than saving it. But I need a solution for my already saved file. My textfile looks like this:
file.txt:
[Hello(i=0, time=0, x=0, y=0), Hello(i=0, time=0, x=0, y=0),...]
[Hello(i=1, time=0, x=0, y=0), Hello(i=0, time=0, x=0, y=0),...]
[Hello(i=2, time=0, x=0, y=0), Hello(i=0, time=0, x=0, y=0),...]
[Hello(i=3, time=0, x=0, y=0), Hello(i=0, time=0, x=0, y=0),...]
If i use the split-method, it is almost as I want it to be, but as expected as strings:
lines = input_data.split('\n')
lines
['[Hello(i=0, time=0, x=0, y=0), Hello(i=0, time=0, x=0, y=0),...]','[Hello(i=1,...),...],...]']
Thank you very much guys!
Upvotes: 0
Views: 478
Reputation: 57033
As much as I hate promoting eval()
, this must be one of those rare cases when any alternative solution is even worse.
line = "[Hello(i=3, time=0, x=0, y=0), Hello(i=0, time=0, x=0, y=0)]"
# Original definition, I assume
Hello = namedtuple('Hello', ['i','time','x','y'])
data = eval(line)
#[Hello(i=3, time=0, x=0, y=0), Hello(i=0, time=0, x=0, y=0)]
NB You should not use eval
in any situation when the data that you read was not previously produced and saved by yourself.
Upvotes: 1
Reputation: 1122182
You'll have to parse your file as text, and extract the information using text manipulation techniques.
You could use a regular expression here:
import re
hello_pattern = re.compile(r'Hello\(i=(\d+), time=(\d+), x=(\d+), y=(\d+)\)')
This pattern matches the representation of your namedtuple values, and gives you access to the numbers for each values, albeit as strings:
>>> line = '[Hello(i=0, time=0, x=0, y=0), Hello(i=0, time=0, x=0, y=0),...]'
>>> hello_pattern.findall(sample)
[('0', '0', '0', '0'), ('0', '0', '0', '0')]
You can then convert those strings to integers again and recreate the instances; for a single line the list comprehension would be:
[Hello(*map(int, match)) for match in hello_pattern.findall(line)]
and a demo of this on the same line:
>>> from collections import namedtuple
>>> Hello = namedtuple('Hello', 'i time x y')
>>> [Hello(*map(int, match)) for match in hello_pattern.findall(sample)]
[Hello(i=0, time=0, x=0, y=0), Hello(i=0, time=0, x=0, y=0)]
So the complete solution would be:
import re
from collections import namedtuple
Hello = namedtuple('Hello', 'i time x y') # or import your own ready definition
hello_pattern = re.compile(r'Hello\(i=(\d+), time=(\d+), x=(\d+), y=(\d+)\)')
data = []
with open('file.txt') as inputfile:
for line in inputfile:
recovered = [
Hello(*map(int, match))
for match in hello_pattern.findall(line)
]
data.append(recovered)
Upvotes: 4