从csv仅一栏转换为dict

时间:2018-08-06 11:12:13

标签: python csv dictionary

已经有朝这个方向提出的问题,但是在我的情况下,我遇到以下问题:

列别名包含字典。如果我使用csv阅读器,则会得到字符串。

我已经用ast eval解决了这个问题,但是它非常慢并且消耗大量资源。

由于编码,备用json.loads不起作用。

解决这个问题的一些想法?

CSV文件:

id;name;partei;term;wikidata;alias
2a24b32c-8f68-4a5c-bfb4-392262e15a78;Adolf Freiherr Spies von Büllesheim;CDU;10;Q361600;{}
9aaa1167-a566-4911-ac60-ab987b6dbd6a;Adolf Herkenrath;CDU;10;Q362100;{}
c371060d-ced3-4dc6-bf0e-48acd83f8d1d;Adolf Müller;CDU;10;Q363453;{'nl': ['Adolf Muller']}
41cf84b8-a02e-42f1-a70a-c0a613e6c8ad;Adolf Müller-Emmert;SPD;10;Q363451;{'de': ['Müller-Emmert'], 'nl': ['Adolf Muller-Emmert']}
15a7fe06-8007-4ff0-9250-dc7917711b54;Adolf Roth;CDU;10;Q363697;{}

代码:

with open(PATH_CSV+'mdb_file_2123.csv', "r", encoding="utf8") as csv8:
    csv_reader = csv.DictReader(csv8, delimiter=';')
    for row in csv_reader:

        if not (ast.literal_eval(row['alias'])):
            pass

        elif (ast.literal_eval(row['alias'])):
            known_as_list = list()

            for values in ast.literal_eval(row['alias']).values():
                for aliases in values:
                    known_as_list.append(aliases)

工作正常,但速度很慢。

2 个答案:

答案 0 :(得分:1)

ast库会消耗大量内存(请参阅this link),我建议在将简单的字典格式字符串转换为python字典时,避免使用该内存。相反,我们可以尝试使用python内置的eval函数来克服由于导入模块而引起的延迟。正如一些讨论所建议的那样,eval在处理敏感字符串时非常危险。示例:eval('os.system("rm -rf /")')。但是,如果我们非常确定csv内容不会携带此类敏感命令,则可以不用担心而使用eval

with open('input.csv', encoding='utf-8') as fd:
    csv_reader = csv.DictReader(fd, delimiter=';')

    for row in csv_reader:
        # Convert dictionary in string format to python format
        row['alias'] = eval(row['alias'])

        # Filter empty dictionaries
        if not bool(row['alias']):
            continue

        known_as_list = [aliases for values in row['alias'].values() for aliases in values]

        print(known_as_list)

输出

C:\Python34\python.exe c:\so\51712444\eval_demo.py
['Adolf Muller']
['Müller-Emmert', 'Adolf Muller-Emmert']

答案 1 :(得分:0)

您可以避免拨打literal_eval三次(一次就足够)了- 当我在清理它的时候,或者我想,您使用的是SO代码 经典(贡献3013次!)

from ast import literal_eval

# https://stackoverflow.com/a/952952/2749397 by Alex Martelli
flatten = lambda l: [item for sublist in l for item in sublist]
...

for row in csv_reader:
    known_as_list = flatten(literal_eval(row['alias']).values())

从OP中显示的数据摘录中,似乎有可能 避免在大部分行上调用literal_eval

...
for row in csv_reader:
    if row['alias'] != '{}':
        known_as_list = flatten(literal_eval(row['alias']).values())