How to read back string, into namedtuple?
import collections
from typing import Sequence, Iterator
import ast
Range = collections.namedtuple("Range", ["key", "min", "max", "in_range" ])
Ranges to string
Test object to string:
r1 = tools.Range(key='T1',min=-0.01,max=0.19, in_range=True)
r2 = tools.Range(key='T2',min=2,max=10, in_range=False)
r3 = tools.Range(key='T3',min=225000,max=1583515.5, in_range=True)
rs = [r1, r2, r3]
rstr = str(rs)
print(rstr)
# output:
# [Range(key='T1', min=-0.01, max=0.19, in_range=True), Range(key='T2', min=2, max=10, in_range=False), Range(key='T3', min=225000, max=1583515.5, in_range=True)]
How to read same or similar string now into object (list of Range)?
Parse back String to Ranges
What I've tried with most hope of success:
source_string = "[Range(key='T1', min=-0.01, max=0.19, in_range=True), Range(key='T2', min=2, max=10, in_range=False), Range(key='T3', min=225000, max=1583515.5, in_range=True)]"
source = ast.literal_eval(source_string)
ranges = tools.Range(key=source["key"],min=float(source["min"]), max=float(source["max"]), in_range=bool(source["in_range"]))
I did also variants, with no success. I am open to change the string syntax to get the ranges object generate.
CodePudding user response:
The ast.literal_eval
function can only parse the following types:
- strings
- bytes
- numbers
- tuples
- lists
- dicts
- sets
- booleans
- None and Ellipsis
This also means that it can only parse a tuple, list, dict, or set containing these specific types. It cannot parse a list of namedtuple
objects. So you will have to either:
- Create your own method that parses a string of the format
"Range(key= ...(etc.)"
, OR - Remove the attribute names/keywords from your string, leaving simply a tuple for each element. You can then use python's built-in
map
function in combination with thenamedtuple._make
method to parse the list of tuples:
source_string = "[('T1', -0.01, 0.19, True), ('T2', 2, 10, False), ('T3', 225000, 1583515.5, True)]"
source = ast.literal_eval(source_string)
ranges = list(map(Range._make, source))
If you really need Range(...)
and/or key=..., min=...
to be a part of the string, you could potentially pre-process the string using regex.