3

I've got a problem with the utilisation of ast.literal_eval(). In the example below, I only want to convert the string (myText) to dictionnary. But ast.literal_eval() try to evaluate <__main__.myClass instance at 0x0000000052D64D88> and give me an error. I completely anderstand this error but I would like to know if there is a way to avoid it (with an other function or with an other way to use the function ast.literal_eval)

import ast

myText = "{<__main__.myClass instance at 0x0000000052D64D88>: value}"
ast.literal_eval(myText)

# Error: invalid syntax
# Traceback (most recent call last):
#   File "<maya console>", line 4, in <module>
#   File "C:\Program Files\Autodesk\Maya2016\bin\python27.zip\ast.py", line 49, in literal_eval
#     node_or_string = parse(node_or_string, mode='eval')
#   File "C:\Program Files\Autodesk\Maya2016\bin\python27.zip\ast.py", line 37, in parse
#     return compile(source, filename, mode, PyCF_ONLY_AST)
#   File "<unknown>", line 1
#     {<__main__.myClass instance at 0x0000000052D64D88>: value}
#      ^
# SyntaxError: invalid syntax # 

Thank you in advance for your help !

Morgan
  • 589
  • 9
  • 20
  • Consider doing it manually, if you know that the `myText` is going to be fairly regular. 1 Strip the braces. 2. Split on comma. 3. Split each resulting string on the colon, and shove the parts into a dictionary. – unwind Apr 21 '15 at 13:58
  • 3
    What do you want to happen here? – Daniel Roseman Apr 21 '15 at 13:58
  • Do you understand what `ast.literal_eval` does? If your example is verbatim, then neither the key nor the value in your dictionary representation is an actual literal. – user4815162342 Apr 21 '15 at 14:01
  • 4
    If you are storing this kind of information as a string, you are probably trying to solve a problem the wrong way. What fundamental problem are you trying to solve/for what do you want to evaluate this string? – syntonym Apr 21 '15 at 14:04
  • 1
    Your data is already irreversibly damaged. Using a smarter parser won't help. – Ignacio Vazquez-Abrams Apr 21 '15 at 14:09
  • I can try to exectute it manually like unwind said. In fact I try to read a text file. In this file I saved attributes of several instances and now I would like to get back these values. So in reality the string that I want to read is more like that : `{<__main__.myClass instance at 0x0000000052D64D88>: {'name': 'theName'}, <__main__.myClass instance at 0x0000000052D73F48>: {'name': 'theName'}}` – Morgan Apr 21 '15 at 14:11
  • Maybe you want to be pickling/unpickling these objects instead. – ABM Apr 21 '15 at 14:14
  • It look like that ABM is right. I don't know was pickling/unpickling is (I am a complete beginner in python) but I just quickly ready some informations about it and it look good for what I want to do. I will search more about it ! Thanks everyone for the help ! – Morgan Apr 21 '15 at 14:23
  • Wow, it's like a textbook example of [XY problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) – Łukasz Rogalski Apr 22 '15 at 09:25

1 Answers1

3

What you really want to do is dump your data using pickle.dump and load it using pickle.load (or equivalent, such as json, etc.). Using repr(data) to dump the data will cause problems like this.

If you just need to salvage the data you have already generated, you might get away with something like the following:

def my_literal_eval(s):
    s = re.sub(r"<__main__.myClass instance at 0x([^>]+)>", r'"<\1>"', s)
    dct = ast.literal_eval(s)
    return {myClass(): v for v in dct.itervalues()}

Example of usage:

>>> import ast, re
>>> class myClass(object): pass
... 
>>> myText = "{<__main__.myClass instance at 0x0000000052D64D88>: {'name': 'theName'}, <__main__.myClass instance at 0x0000000052D73F48>: {'name': 'theName'}}"
>>> my_literal_eval(myText)
{<__main__.myClass object at 0x7fbdc00a4b90>: {'name': 'theName'}, <__main__.myClass object at 0x7fbdc0035550>: {'name': 'theName'}}

This will work only if the myClass instances don't have any useful information, but are only needed for identity. The idea is to first fix up the string by replacing the <__main__.myClass instance ...> strings with something that can be parsed by ast.literal_eval, and then replace those with actual myClass instances - provided these can be constructed without arguments, which hinges on the above assumption.

If this initial assumption doesn't hold, then your data is, as Ignacio put it, irreversibly damaged, and no amount of clever parsing will retrieve the lost bits.

Community
  • 1
  • 1
user4815162342
  • 141,790
  • 18
  • 296
  • 355