Converting String Representations of Dictionaries
Sometimes you might encounter a dictionary stored as a string. This can happen when reading data from a file, receiving data over a network, or when a dictionary has been serialized (converted into a string format) for storage or transmission. You’ll need to convert this string back into a usable Python dictionary. This tutorial will explore several methods to achieve this, with a focus on safety and efficiency.
The Problem
Imagine you have a string that looks like a dictionary:
s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"
This isn’t a dictionary yet; it’s just a string. You need to parse this string and convert it into a Python dict
object to work with it.
Naive Approach: eval()
(and Why It’s Generally a Bad Idea)
A simple, but potentially dangerous, way to achieve this is using the eval()
function:
s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"
d = eval(s)
print(d) # Output: {'muffin': 'lolz', 'foo': 'kitty'}
print(type(d)) # Output: <class 'dict'>
Why is eval()
dangerous? eval()
executes arbitrary Python code. If the string you’re evaluating comes from an untrusted source (e.g., user input or a network connection), it could contain malicious code that compromises your system. Never use eval()
on untrusted data.
Safe Alternatives
Several safer alternatives exist for converting string representations of dictionaries:
1. json.loads()
The json
module is designed for working with JSON (JavaScript Object Notation) data, a common format for data interchange. JSON is a subset of Python’s dictionary syntax. This is usually the preferred method if your string is in a valid JSON format.
import json
s = '{"muffin" : "lolz", "foo" : "kitty"}' # Note: JSON requires double quotes
d = json.loads(s)
print(d) # Output: {'muffin': 'lolz', 'foo': 'kitty'}
print(type(d)) # Output: <class 'dict'>
Important: json.loads()
requires double quotes for both keys and values. If your string uses single quotes, you’ll need to replace them before using json.loads()
.
import json
s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"
s = s.replace("'", "\"") # Replace single quotes with double quotes
d = json.loads(s)
print(d)
2. ast.literal_eval()
The ast
(Abstract Syntax Trees) module provides a safer alternative to eval()
. The ast.literal_eval()
function can parse a string containing a Python literal (like a dictionary, list, number, string, boolean, or None
).
import ast
s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"
d = ast.literal_eval(s)
print(d) # Output: {'muffin': 'lolz', 'foo': 'kitty'}
print(type(d)) # Output: <class 'dict'>
ast.literal_eval()
is much safer than eval()
because it only parses literal structures and doesn’t execute arbitrary code.
3. yaml.load()
The PyYAML
library can load YAML (YAML Ain’t Markup Language) formatted strings. This is useful if the string representation of your dictionary is in YAML format. First, you’ll need to install it: pip install pyyaml
.
import yaml
s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"
d = yaml.load(s)
print(d) # Output: {'muffin': 'lolz', 'foo': 'kitty'}
print(type(d)) # Output: <class 'dict'>
While flexible, yaml.load
can have security concerns if used with untrusted input. It’s best to avoid it unless you specifically need to parse YAML and trust the source of the data.
Choosing the Right Method
json.loads()
: Best if your string is in valid JSON format (double quotes). It’s generally the fastest and most efficient option for JSON data.ast.literal_eval()
: A safe option for parsing simple Python literals like dictionaries, lists, numbers, and strings. Useful when you don’t know if the string is valid JSON and you want a safe parsing method.yaml.load()
: Use only when parsing YAML and you fully trust the source of the data.