Python:在没有引号的文件中保存列表?

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

我正在使用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.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

为什么不改用Pandas
DataFrame
类?它更好地覆盖不同的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文件小得多。如果数据框中也有多个列表作为列,则此方法也有效。