Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从csv导入字典包含列表_Python_List_Csv_Dictionary - Fatal编程技术网

Python 从csv导入字典包含列表

Python 从csv导入字典包含列表,python,list,csv,dictionary,Python,List,Csv,Dictionary,我有一个字典,其中包含一个列表作为值(见下文),并希望将其保存到csv。到目前为止,保存工作还不错,但当我将其读回我的程序时,我得到了以下结果,其中两个列表[1,2,3]和[4,5,6]不再是列表,而是字符串(“[1,2,3]”和“[4,5,6]”) 如何将列表作为列表而不是字符串从csv加载?这样我就可以再次访问列表中的元素,而不是单个字符(见下文) 结果: {'Key': 'key1', 'List': '[1, 2, 3]'} {'Key': 'key2', 'List': '[4, 5,

我有一个字典,其中包含一个列表作为值(见下文),并希望将其保存到csv。到目前为止,保存工作还不错,但当我将其读回我的程序时,我得到了以下结果,其中两个列表[1,2,3]和[4,5,6]不再是列表,而是字符串(“[1,2,3]”和“[4,5,6]”)

如何将列表作为列表而不是字符串从csv加载?这样我就可以再次访问列表中的元素,而不是单个字符(见下文)

结果:

{'Key': 'key1', 'List': '[1, 2, 3]'}
{'Key': 'key2', 'List': '[4, 5, 6]'}
问题:

现在列表是字符串,我无法访问列表中的数字,因为它现在是一个字符列表

>> print nodes[0]['List'][0] # print first number from list in first dictionary
[
有没有人能帮我或给我一个替代方案?
提前多谢

CSV并不是专门用来以这种方式存储嵌套列表的。您可以使用
eval
,但这是一个相当大的安全问题,因为它允许人们在您的计算机上运行代码,例如,如果您让人们将其文件上载到您的服务器上。相反,我建议您将字典存储为JSON对象。这将处理很多以后可能出现的特殊情况

import json

test_list = [{'Key' : 'key1', 'List' : [1,2,3]}, 
        {'Key' : 'key2', 'List' : [4,5,6]}]

with open('/tmp/test_list.json', 'w') as f:
    json.dump(test_list, f)
然后加载它:

with open('/tmp/test_list.json') as f:
    test_list = json.load(f)
我会用泡菜

import pickle

test_list = [{'Key' : 'key1', 'List' : [1,2,3]},
                {'Key' : 'key2', 'List' : [4,5,6]}]

pickle.dump(test_list,open('list.p','wb'))
test_list = pickle.load(open('list.p','rb'))
print test_list

>>> [{'List': [1, 2, 3], 'Key': 'key1'}, {'List': [4, 5, 6], 'Key': 'key2'}]

我同意@Jimmy:csv并不非常适合存储列表。正如他所建议的,切换到JSON是最好的现成解决方案

如果出于某种原因您不能或不想切换到JSON,那么您应该自己打包列表,以便它们可以作为CSV中的单个单元格存储和检索,并自己处理解包如果所有列表数据都是整数列表,则可以按如下方式打包和解包:

...
for entry in test_list:
    entry["List"] = ",".join( str(n) for n in entry["List"] )
    writer.writerow(entry)

# Reading in
for row in csv.DictReader(f, delimiter=';'):
    row["List"] = [ int(n) for n in row["List"].split(",") ]
    nodes.append(row)

因为您在CSV中使用“;”作为字段分隔符,所以我使用“,”作为列表分隔符。如果编写器正确引用,则不需要这样做,但这样做会更简洁。

这里的根本问题是CSV只存储字符串。因此,将
列表
放在CSV单元格中本质上意味着自动对该列表进行字符串化,然后迫使您再次解析它

如果这个列表真的只是一个整数列表,那么它将起作用。(这个列表应该只是一个整数列表,但事实证明它是不同的,无论是因为bug,还是因为恶意用户,它都会给你一个很好的错误,而不是默默地做一些危险的事情,或者引发一些毫无意义的令人困惑的异常。)但这很少是一个好主意。Python的
repr
不是一种数据序列化或交换格式;它是一种帮助人类程序员理解数据的格式

本教程的这一章解释了用于数据序列化和交换的选项:
json
pickle
,以及stdlib中的
csv
*。或者你可以使用第三方模块,比如
PyYAML
,或者将东西存储在数据库中,等等。如果你仔细阅读了每一个模块的优缺点,
json
是本例中显而易见的答案,如图所示



*是的,您可以在CSV文件的一行中使用逗号分隔值列表,只要您使用不同的分隔符,或者允许
CSV
引用内容。请参阅以获得一种简单的方法,或者通过递归使用
csv.writer
csv.reader
搜索ActiveState配方以获得一种存储两级列表的奇特方法。但通常,你不想这样做;JSON的优点是可以任意递归,而不仅仅是两级递归,更大的优点是使用非常简单。

为什么不将DICT用JSON呢?您甚至可以在
csv.reader(delimiter=',')的单元格上递归地使用
csv.reader(delimiter=';')
。ActiveState上的某个地方有一个菜谱可以很好地概括这一点。真正有趣的是从那里链接的菜谱,它使用引用实现任意级别的递归。你可以想象Excel风格的引用会是什么样子,它用引号转义引号字符……我想理论上它仍然是人类可编辑的,我只是还没有遇到可以这样做的人。:)如果我没记错的话,没有嵌入引号的标准方法,对吗?有些系统会识别反斜杠,有些系统会将引号翻一番……结果一定是不可移植性的纪念碑。这个应用程序听起来像是切换到JSON的海报子程序。这就是为什么您必须指定一种方言(通过名称,或通过组合所有单独的方言变体参数)。当然,猜测错误的方言可能意味着,无论您尝试与哪个程序进行交互,都可以毫无怨言地打开您的文件,但不会给出您想要的结果,这使得调试更加有趣……无论如何,您是对的,它是JSON的典型代表。我也对您的答案投了赞成票,但我希望OP接受J为什么要使用
pickle
而不是
JSON
?它有相同的界面,但它提供的结果不是人类可读的或可编辑的(或JavaScript/Ruby/etc.-readable),增加了潜在的安全漏洞,等等。
pickle
在需要存储JSON无法处理的数据时非常有用(或者当您需要紧凑性,但不使用默认的pickle协议0时,它通常比JSON更慢、更大……),但是当JSON可以的时候,为什么不使用它呢?我倾向于使用
pickle
,因为它比
JSON
更灵活,例如,
pickle
可以序列化一个类。但是,使用人类可读和跨语言可编辑的
JSON
也很好。在我看来,其中任何一个都可以,我只想介绍
pickle
模块,以防OP尚未接触到它。
pickle
的问题在于它非常灵活。它会打开潜在的安全漏洞和健壮性问题(例如,如果在版本之间更改类,则必须小心不要破坏pickle),调试pickle比JSON有趣得多
...
for entry in test_list:
    entry["List"] = ",".join( str(n) for n in entry["List"] )
    writer.writerow(entry)

# Reading in
for row in csv.DictReader(f, delimiter=';'):
    row["List"] = [ int(n) for n in row["List"].split(",") ]
    nodes.append(row)