Reputation: 51
I have a text file in the below format
d = {'EMS':1,'ESC': 2, 'HVAC': 3,'IC' : 4,'ICU' : 5,'IS' : 6,'ITM' : 7,'MBFM' : 8,'PKE' : 9,'RPAS' : 10,'RVC' : 11,'SAS' : 12,'SRS' : 13,'TCU' : 14,'TPMS' : 15,'VCU' : 16,'BMS' : 17,'MCU' :18,'OBC' :19}
How do I read the dictionary to find the value a particular value?
I have tried the below code
with open(r"filename","r") as f:
data = ast.literal_eval(f.read())
print(data)
for age in data.values():
if age == search_age:
name = data[age]
print (name)
Upvotes: 3
Views: 2360
Reputation: 23563
I like the accepted answer by @blhsing, but what if you want a dictionary by a specific variable name? At least that is what I was looking for.
Slight variation of @blhsing 's answer, using ast.Assign
since that will have ast.Name
and ast.Dict
as its children.
import ast
from path lib import Path
def walk_file(dict_name, path):
t = ast.parse(Path(path).read_text())
return walk(dict_name, t)
def walk(dict_name, t):
for node in ast.walk(t):
if (
isinstance(node, ast.Assign)
and isinstance(node.value, ast.Dict)
and node.targets[0].__dict__.get("id") == dict_name
):
if not any(
isinstance(child, ast.Call) for child in ast.walk(node)
):
value = ast.literal_eval(node.value)
return value
else:
print("uh oh, callables found!")
else:
print("No valid dict found.")
So for example,
blah = """
d1 = {"hi": 2}
def foo():
d2 = {"hmm": {"interesting": [1, 2]}}
d3 = {"sure": "great"}
"""
t = ast.parse(blah)
for name in ["d1", "d2", "d3"]:
print(name, walk(name, t))
d1 {'hi': 2}
d2 {'hmm': {'interesting': [1, 2]}}
d3 {'sure': 'great'}
Upvotes: 0
Reputation: 107124
Your text file is a valid Python code, so if it is from a trusted source, you can simply do:
with open("filename") as f:
exec(f.read())
and the variable d
would be loaded with the dict.
If the text file is not from a trusted source, however, you can use ast.parse
to parse the code, then use ast.walk
to traverse the abstract syntax tree and look for a Dict
node. For security reasons, make sure the dict node does not contain any Call
node before wrapping it as the body of an Expression
node and compiling it for eval
to turn it into a real dict stored in variable d
:
import ast
with open("filename") as f:
for node in ast.walk(ast.parse(f.read())):
if isinstance(node, ast.Dict) and \
not any(isinstance(child, ast.Call) for child in ast.walk(node)):
d = eval(compile(ast.Expression(body=node), '', 'eval'))
break
else:
print('No valid dict found.')
Given your sample input, d
would become:
{'EMS': 1, 'ESC': 2, 'HVAC': 3, 'IC': 4, 'ICU': 5, 'IS': 6, 'ITM': 7, 'MBFM': 8, 'PKE': 9, 'RPAS': 10, 'RVC': 11, 'SAS': 12, 'SRS': 13, 'TCU': 14, 'TPMS': 15, 'VCU': 16, 'BMS': 17, 'MCU': 18, 'OBC': 19}
Upvotes: 4
Reputation: 19905
You need to iterate over both the keys and values:
with open('filename') as f:
data = ast.literal_eval(f.read())
print(data)
for name, age in data.items():
if age == search_age:
print(name)
Also, that file looks like a valid JSON object, so you should probably use json.load
over ast.literal_eval
.
Upvotes: 0