简体   繁体   中英

Reading from text-file with namedtuple entries

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!

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)

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM