Python:在没有引号的文件中保存列表?
我正在使用csv模块处理一些文本文件,我遇到了一些我无法理解的奇怪问题。到目前为止,我的代码是:Python:在没有引号的文件中保存列表?,python,list,csv,python-2.x,tab-delimited-text,Python,List,Csv,Python 2.x,Tab Delimited Text,我正在使用csv模块处理一些文本文件,我遇到了一些我无法理解的奇怪问题。到目前为止,我的代码是: import csv with open('file1.txt', 'r') as a: with open('file2.txt', 'w+') as b: reader = csv.reader(a, delimiter = '\t') writer = csv.writer(b, delimiter = '\t', quoting = csv.QUOT
import csv
with open('file1.txt', 'r') as a:
with open('file2.txt', 'w+') as b:
reader = csv.reader(a, delimiter = '\t')
writer = csv.writer(b, delimiter = '\t', quoting = csv.QUOTE_NONE, escapechar = '')
for row in reader:
# Do stuff
writer.writerow(row)
# Check datatypes of each column
print(type(row))
print(type(row[0]))
print(type(row[1]))
print(type(row[2]))
print(type(row[3]))
print(type(row[4]))
print(row)
输出:
<type 'list'>
<type 'str'>
<type 'str'>
<type 'list'>
<type 'str'>
<type 'list'>
['blah', 'blah', ['01', '02', '03', '04'], 'blah', ['0', '0', '0', '0']]
['blah', 'blah', "['01', '02', '03', '04']", 'blah', "['0', '0', '0', '0']"]
<type 'list'>
<type 'str'>
<type 'str'>
<type 'str'>
<type 'str'>
<type 'str'>
输出:
<type 'list'>
<type 'str'>
<type 'str'>
<type 'list'>
<type 'str'>
<type 'list'>
['blah', 'blah', ['01', '02', '03', '04'], 'blah', ['0', '0', '0', '0']]
['blah', 'blah', "['01', '02', '03', '04']", 'blah', "['0', '0', '0', '0']"]
<type 'list'>
<type 'str'>
<type 'str'>
<type 'str'>
<type 'str'>
<type 'str'>
['blah','blah','01','02','03','04'],'blah','0','0','0']]
请注意,第3个和第5个值周围有双引号。这些值是如何转换为字符串的!?这对我来说很奇怪。我真的需要第3列和第5列是列表类型,而不是字符串,以便能够进一步处理它
我的问题是,如何将第3列和第5列的值转换回列表类型,或者更好,如何首先防止它们保存为字符串
请让我知道,如果我需要进一步澄清我的问题,请帮助我处理这种情况
编辑:因此,我了解到不可能阻止将这些值存储为字符串,因此我现在正在考虑是否可以将这些值作为列表来处理。我真的不在乎值如何存储在文件中,只要我把它们作为列表来处理。你不能阻止它们被保存为字符串。显然,CSV是一个文本文件;它对列表一无所知。通过调用
str()
,任何传递到csv.writerow
的内容都将转换为字符串。如果生成的字符串包含逗号,它本身将被引用,这样很明显,逗号是元素的一部分,而不是表示新元素的分隔符
无法自动转换回列表。如果您知道每一行的第2列应该是一个列表,您可以手动将其转换回-一种方法是使用
ast.literal\u eval
为什么不改用PandasDataFrame
类?它更好地覆盖不同的CSV规范,更好地控制各个列的数据类型。看看这个。您可以很容易地读取CSV,然后使用另一个分隔符写入另一个CSV。我认为您需要将行展平,以便将列表列表转换为单个列表
以下是一个例子:
def flatten(seq):
result = []
for item in seq:
if isinstance(item, list):
result.extend(item)
else:
result.append(item)
return result
简单用法:
row = ['blah', 'blah', ['01', '02', '03', '04'], 'blah', ['0', '0', '0', '0']]
row = flatten(row)
# -> ['blah', 'blah', '01', '02', '03', '04', 'blah', '0', '0', '0', '0']
我会像这样更正您的代码:
import csv
with open('file1.txt', 'r') as a:
with open('file2.txt', 'w+') as b:
reader = csv.reader(a, delimiter = '\t')
writer = csv.writer(b, delimiter = '\t', quoting = csv.QUOTE_NONE, escapechar = '')
for row in reader:
# Do stuff
writer.writerow(flatten(row))
使用
pickle
可以将对象(本例中为列表)保存为序列化字节流,然后可以将其加载回并将该字节流重新转换为python对象
下面是一个如何工作的示例
import pickle
writer = ['foo', 'bar', ['foo', 'bar'], 2]
pickle.dump(writer, open('file2.p', 'wb'))
使用pickle加载file2.p
时,它将被重新转换为其原始对象:
writer = pickle.load(open('file2.p', 'rb'))
print(writer)
给
['foo', 'bar', ['foo', 'bar'], 2]
编辑:
要创建编写器
:
import csv
writer = []
with open('file1.txt', 'r') as a:
reader = csv.reader(a, delimiter = '\t')
for row in reader:
writer.append(row)
对于每个项目,请检查其方括号,然后使用列表(行[索引])将其转换。当您序列化
列表时,CSV编写器会将其转换为字符串,以便获得引号:str(['01','02','03','04'])=>“['01','02','03','04']”
您可能想尝试pickle
或cPickle
来直接保存和加载列表对象。@RodrigoDorantes Gilardi您能举个例子吗?哦,实际上这是一个多么糟糕的问题。我尝试了list(literal\u eval(row[2]))
和print(row[2][0])
prints[
,这意味着row[2]
仍被视为一个字符串。你能用literal\u eval
的正确用法更新你的答案吗?很抱歉,扁平化超出了我的选择范围,因为在这种情况下,我将无法访问row[2]
类似于我想要的列表的元素,例如行[2][0]
访问'01'
。你真的需要CSV吗?JSON格式更适合封装对象。事实上,我正在处理的文件可以作为制表符分隔的CSV文件使用。所以,我在那里真的没有太多自由。好吧,那么使用Daniel的答案。你有:断言ast.literal_eval(str(['1','2','3'])=['1','2','3'])ˋ。这对我很有效。保存为pickle文件也会使其比csv文件小得多。如果数据框中也有多个列表作为列,则此方法也有效。