I could do this with eval():
>>> s = 'hello=True,world="foobar"'
>>> eval('dict('+s+')')
{'hello': True, 'world': 'foobar'}
but with literal_eval():
>>> from ast import literal_eval
>>> literal_eval('dict('+s+')')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/Cellar/python@3.11/3.11.3/Frameworks/Python.framework/Versions/3.11/lib/python3.11/ast.py", line 110, in literal_eval
return _convert(node_or_string)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/Cellar/python@3.11/3.11.3/Frameworks/Python.framework/Versions/3.11/lib/python3.11/ast.py", line 109, in _convert
return _convert_signed_num(node)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/Cellar/python@3.11/3.11.3/Frameworks/Python.framework/Versions/3.11/lib/python3.11/ast.py", line 83, in _convert_signed_num
return _convert_num(node)
^^^^^^^^^^^^^^^^^^
File "/usr/local/Cellar/python@3.11/3.11.3/Frameworks/Python.framework/Versions/3.11/lib/python3.11/ast.py", line 74, in _convert_num
_raise_malformed_node(node)
File "/usr/local/Cellar/python@3.11/3.11.3/Frameworks/Python.framework/Versions/3.11/lib/python3.11/ast.py", line 71, in _raise_malformed_node
raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string on line 1: <ast.Call object at 0x1014cb940>
Q (part 1): Why would eval() work but not literal_eval()?
Q (part 2): Is there a name for the '+s+' style/format?
Q (part 3): Is it possible to use something like the +s+ with literal_eval()?
>Solution :
This isn’t special syntax: +s+ doesn’t have any atypical meaning. You’re just concatenating strings together, the same way 'abc' + 'def' evaluates to 'abcdef'.
In this case, when you concatenate the string 'dict(', the string 'hello=True,world="foobar"', and the string ')' together, you get 'dict(hello=True,world="foobar")'.
dict(hello=True,world="foobar") is valid Python code (so eval can run it), but it’s not a valid literal definition (because dict is a function call, not literal syntax), so ast.literal_eval() correctly refuses it.