ValueError: malformed node or string in Python [Solved]

avatar
Borislav Hadzhiev

Last updated: Apr 10, 2024
4 min

banner

# ValueError: malformed node or string in Python [Solved]

The Python "ValueError: malformed node or string" occurs for 3 main reasons:

  1. Passing a value that is not a string to the ast.literal_eval() method.
  2. Passing a JSON string to the method (use json.loads() instead).
  3. Passing a string that is syntactically incorrect to the method.

To solve the error, use the str() class to convert the value to a string or make sure to only call the ast.literal_eval() method with strings.

valueerror malformed node or string

Here is an example of how the error occurs.

main.py
import ast a_dict = { 'first': 'bobby', 'last': 'hadz', } # โ›”๏ธ ValueError: malformed node or string: {'first': 'bobby', 'last': 'hadz'} print(ast.literal_eval(a_dict))

malformed node or string in python

We called the ast.literal_eval method with a dictionary instead of a string which caused the error.

The method evaluates a string that contains a Python literal.

The string may consist of the following objects:

  • strings
  • bytes
  • numbers
  • tuples
  • lists
  • dictionaries
  • sets
  • booleans
  • None

Note that the method expects to get called with the string representation of the given object, not the object itself (not a dictionary, list or set).

Here is an example of using the ast.literal_eval() method correctly.

main.py
import ast a_str = '''{ "first": "bobby", "last": "hadz" }''' result = ast.literal_eval(a_str) print(result) # ๐Ÿ‘‰๏ธ {'first': 'bobby', 'last': 'hadz'} print(type(result)) # ๐Ÿ‘‰๏ธ <class 'dict'>

using ast literal eval to solve error

The code for this article is available on GitHub

Notice that we passed a string to the method and not a dictionary.

The string in the example is a valid dictionary, so it gets parsed to a native Python dict object by the literal_eval() method.

# Converting the object to a string in the call to ast.literal_eval()

One way to solve the error is to use the str() class to convert the object to a string in the call to the ast.literal_eval() method.

main.py
import ast a_dict = { 'first': 'bobby', 'last': 'hadz', } result = ast.literal_eval(str(a_dict)) print(result) # ๐Ÿ‘‰๏ธ {'first': 'bobby', 'last': 'hadz'} print(type(result)) # ๐Ÿ‘‰๏ธ <class 'dict'>

convert object to string in call to ast literal eval

The code for this article is available on GitHub

We used the str() class to convert the dictionary to a string in the call to the method.

No error is raised because the method is called with a string argument.

However, the conversion shouldn't be necessary and could lead to performance issues if the given value is a very large dictionary or list.

# Checking if the supplied value is a string before calling literal_eval()

An alternative approach is to use the isinstance() function to check if the value is a string before calling the ast.literal_eval() method.

main.py
import ast a_dict = { 'first': 'bobby', 'last': 'hadz', } if isinstance(a_dict, str): result = ast.literal_eval(a_dict) else: result = a_dict print(result) # ๐Ÿ‘‰๏ธ {'first': 'bobby', 'last': 'hadz'} print(type(result)) # ๐Ÿ‘‰๏ธ <class 'dict'>

check if supplied value is string before calling literal eval

The code for this article is available on GitHub

We only call the ast.literal_eval() method if the value is a string.

Otherwise, we set the result variable to the value.

This helps us avoid the redundant conversion to string.

I've written a detailed article on how to convert the string representation of a list to a list.

The code samples also apply to dictionaries.

Note that calling the ast.literal_eval() method with a string that is not a valid Python object would raise an error.

main.py
import ast a_str = '''{ "first": "bobby", "last": "hadz", "hello" "world" }''' # โ›”๏ธ ERROR result = ast.literal_eval(a_str)

trying to parse invalid object causes an error

Notice that the last key-value pair in the dictionary is not separated by a colon.

Trying to parse an invalid object causes an error.

# Use the json.loads() method if parsing JSON data

Make sure you aren't using the ast.literal_eval() method to parse a JSON string.

Here is an example of how this causes an error.

main.py
import ast a_str = '''{ "first": "bobby", "last": "hadz", "is_programmer": true, "salary": null }''' # โ›”๏ธ ValueError: malformed node or string on line 4: result = ast.literal_eval(a_str)

The string is valid JSON, however, it should not be parsed using ast.literal_eval().

JSON strings contain lowercase boolean values (true and false) and Python booleans have a capital first letter (True and False).

Similarly, we have null in JSON vs None in Python.

Instead, you should use the json.loads() method to convert the JSON string to a native Python object.

main.py
import json a_str = '''{ "first": "bobby", "last": "hadz", "is_programmer": true, "salary": null }''' result = json.loads(a_str) # ๐Ÿ‘‡๏ธ {'first': 'bobby', 'last': 'hadz', 'is_programmer': True, 'salary': None} print(result) print(type(result)) # ๐Ÿ‘‰๏ธ <class 'dict'>

use json loads to convert json string to python object

The code for this article is available on GitHub

The json.loads() method parses a JSON string into a native Python object.

I've written a detailed article on how to convert a JSON string to a native Python object.

If you need to convert the string representation of an object to a Python object, check out the following article instead.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev