如何从文本文件中读取字典?

3

我可以帮你翻译。以下是最初的回答:

我有一个文本文件,格式如下:

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}

如何从字典中找到特定值的值?

我尝试了以下代码

Original Answer翻译成"最初的回答"

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)

那么,代码有什么问题? - Klaus D.
1
@Tejesh Reddy从文件中删除d = 。很可能这是问题所在。 - Jab
这是一个有效的Python模块。将其重命名为filename.py,然后使用from filename import d导入它。就这样,你现在拥有了自己的字典。 - constt
3个回答

3

您的文本文件是有效的Python代码,因此如果它来自可信源,则可以简单地执行以下操作:

with open("filename") as f:
    exec(f.read())

变量d将会被加载为字典,如果文本文件不来自可信来源,则可以使用ast.parse解析代码,然后使用ast.walk遍历抽象语法树并查找Dict节点。出于安全原因,请确保字典节点在包装为Expression节点的主体并编译为eval以将其转换为存储在变量d中的真实字典之前,不包含任何Call节点:

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.')

根据您提供的示例输入,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}

0
你需要同时迭代键和值:
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)

另外,那个文件看起来像是一个有效的 JSON 对象,所以你应该使用 json.load 而不是 ast.literal_eval

我尝试了这个,得到了以下错误: 文件 "C:\Python37-32\lib\ast.py",第46行,在literal_eval函数中: node_or_string = parse(node_or_string, mode='eval') 文件 "C:\Python37-32\lib\ast.py",第35行,在parse函数中: return compile(source, filename, mode, PyCF_ONLY_AST) 在未知位置,第1行: 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} ^ 语法错误:无效的语法 - Tejesh Reddy
@TejeshReddy 你的文件本身格式不正确。请将 d = 删除。 - gmds

0

我喜欢@blhsing给出的答案,但如果你想要一个特定变量名称的字典呢?至少这就是我在寻找的。

对@blhsing答案的稍微变化,使用ast.Assign,因为它会有ast.Nameast.Dict作为其子节点。

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.")

所以举个例子,
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'}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接