Convert a string to a list and back

211 views Asked by At

I feel like this is a strange request. I'm starting with a string, and then I run that through a function that process the string (many lines) and returns a list. This list contains timestamps, and text. It's an LRC file, actually (Lyric with track time)

I'm writing a few kodi (xmbc) modules, and it runs its own python interpreter. I can share data between addons but only as strings. (setting them as a property in kodi)

So, I have a list that I can convert to a string easily with str(), but I can't get it back into the same list that I can deal with.

Some example text:

[01:45.17]<i>I cant remember anything
[01:48.80]Cant tell if this is true or dream
[01:52.29]Deep down inside I feel to scream
[01:55.91]This terrible silence stops me

This comes back from my parser function as a list. In raw form looks like this:

[{'timestamp': dbus.Int64(105170L), 'id': dbus.UInt32(0L), 'text': 'I cant remember anything'}, {'timestamp': dbus.Int64(108800L), 'id': dbus.UInt32(1L), 'text': 'Cant tell if this is true or dream'}, {'timestamp': dbus.Int64(112290L), 'id': dbus.UInt32(2L), 'text': 'Deep down inside I feel to scream'}, {'timestamp': dbus.Int64(115910L), 'id': dbus.UInt32(3L), 'text': 'This terrible silence stops me'}]

Once I convert this to a string with str() it looks exactly like what is above as a string.

Now, I want to get this string back into the original list form. So that I can do line by line processes on it, and reference the elements, as I can with the pre-converted list:

print line['text']
print line['timestamp']

I've tried various things, but can't seem to get it back into a list I can loop through.

I looked at json.dumps ('lines' is the list):

lines_str=json.dumps(lines)
newlines=json.dumps(lines_str)

print newlines.__class__.__name__

But this tells me that lines is still a "str" So, I tried with eval:

lines_str=str(lines)
newlines=eval(lines_str)

But eval doesn't like the string format:

Traceback (most recent call last):
  File "./l.py", line 33, in <module>
    newlines=eval(lines_str)
  File "<string>", line 1, in <module>

then I tried literal_eval from the ast module:

lines_str=str(lines)
newlines=ast.literal_eval(lines_str)

But that liked my string even less.

  File "/usr/lib/python2.7/ast.py", line 79, in _convert
    raise ValueError('malformed string')
ValueError: malformed string

I could perform this task in one addon versus the other. But in the spirit of design, I have a back-end that does the work, and the front-end that paints the pretty pictures. I'd prefer to keep the work on the back-end and minimize loading modules and processes on the front-end piece.

3

There are 3 answers

0
jgauthier On

I did not write this function originally, and I don't know why the author used dbus.types.

So, there are two solutions:

Use json.dumps and json.loads correctly, which I was not doing.

Or, remove the dbus.types and used standard python types.
Doing the latter allowed me to convert using str() and eval() which is what I preferred over loading modules.

Thanks!

0
2rs2ts On

Well, in general, I would just use string formatting on each line separately, and then join them with newlines. I'll assume you have some function from_dbus_int64 that turns a dbus.Int64 into your timestamp format, since I don't know anything about dbus.

def from_parsed_line(line):
    return "{timestamp}{text}".format(
        timestamp=from_dbus_int64(line["timestamp"]),
        text=line["text"]
    )

Then you could just use "\n".join(from_parsed_line(line) for line in lines).

One thing I noticed is that your sample had <i> in the first line but your parsed data didn't have it in the text. Unless you can explain to me why that is, I can't help you put that back in there. I assume you can figure it out.

0
Slam On

Not sure about format, but looks like you need pair of json.dumps (serializes data structure to string, which you have already) and json.loads (which do exactly opposite). And iterate and get keys/values you need after deserializing your strings.