Python: 将列表保存在不带引号的文件中?

Python: Saving list in a file without quotes?

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

我很高兴,直到我再次打开 file2.txt 进行进一步处理,但我不能,因为我得到了令人困惑的结果,所以我再次检查了类型,这次输出不同。

with open('file2.txt', 'r+') as c:

    reader = csv.reader(c, delimiter = '\t')

    for row in reader:
        print(row)
        print(type(row))
        print(type(row[0]))
        print(type(row[1]))
        print(type(row[2]))
        print(type(row[3]))
        print(type(row[4]))

输出:

['blah', 'blah', "['01', '02', '03', '04']", 'blah', "['0', '0', '0', '0']"]
<type 'list'>
<type 'str'>
<type 'str'>
<type 'str'>
<type 'str'>
<type 'str'>

注意第 3 个和第 5 个值周围的双引号。这些值是如何转换为字符串的!?这对我来说很奇怪。我真的需要第 3 和第 5 列是列表类型而不是字符串才能进一步处理它。

我的问题是,如何将第 3 列和第 5 列的值转换回列表类型,或者如何更好地防止它们首先被保存为字符串?

如果我需要进一步澄清我的问题,请告诉我,请帮助我处理这种情况。

编辑: 所以,我了解到无法阻止将这些值存储为字符串,所以我现在在考虑是否可以开始工作这些值作为列表。我真的不在乎值是如何存储在文件中的,只要我将它们作为列表来处理即可。

您无法阻止将它们另存为字符串。显然,CSV 是一个文本文件;它对列表一无所知。传递给 csv.writerow 的任何内容都将通过调用 str() 转换为字符串。如果生成的字符串包含逗号,它本身将被引用,以便很明显逗号是元素的一部分,而不是表示新元素的分隔符。

无法自动转换回列表。如果您知道每一行的第 2 列应该是一个列表,您可以手动将其转换回来 - 一种方法是使用 ast.literal_eval.

为什么不使用 Pandas DataFrame class 呢?它更好地覆盖了不同的 CSV 规范,并且更好地控制了各个列的数据类型。检查此 link。您可以读取 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]

编辑:

创建writer:

import csv
writer = []
with open('file1.txt', 'r') as a:
    reader = csv.reader(a, delimiter = '\t')
    for row in reader:
        writer.append(row)