.readlines() 返回空列表(已解决) -> 使用 csv 将数据添加到特定的命名行

.readlines() returns empty list (solved) -> using csv to add data to a specific named row

提问人:amy-elouise 提问时间:7/26/2023 最后编辑:amy-elouise 更新时间:7/26/2023 访问量:73

问:

在编写了一个函数来生成一些数据之后,我想添加保存它的功能。我最初从以下代码开始,我用'save=True'运行:

[in]
import csv
... (main body of code - all this works fine)
if save is True:
    print("Saving...")
    with open('dataset.csv', 'a+') as f:
        lines = f.readlines()
        for line in lines:
            linesplit = line.split(",")
            name_in_dataset = linesplit[0] 
            ...

            (... some code for the actual saving process - irrelevant)
            
            print("Data added successfully")

[out]
Saving...

我知道数据集文件包含此名称,应该保存在这里,所以我对它出错的地方有点困惑。我开始分解代码,直到我达到这个:

[in]
if save is True:
    print("Saving...")
    with open('dataset.csv') as f:
        lines = f.readlines()
        print(lines)

[out]
Saving...
[]

不太确定为什么它无法读取行?虽然我以前使用过相同的代码来读取这个文件的行,但我真的很困惑为什么它现在不起作用。

我尝试在代码中添加一些东西,例如,但这没有任何区别。我也尝试将打开函数更改为 and,但可惜它无法读取这些行。我搜索了很多关于这个帖子的帖子,找不到任何遇到这种:(的人我觉得我刚刚工作了太久,忘记了 Python 编码的基本原理!f.seek(0)'a''r'.readlines()

提前致谢 <3

编辑: 使用评论中的建议,我将代码更改为:

with open('(file path)/dataset.csv', 'r') as f:
     f.seek(0)
     lines = csv.reader(f)
     print(lines)

它返回:

Saving...
<csv.reader object at 0x7f01282c7f20>
python 列出 csv readlines

评论

0赞 Michael Butscher 7/26/2023
尝试使用绝对路径,因为相对路径可能不指向预期位置。
0赞 Stitt 7/26/2023
您使用而不是使用的原因是什么?如果不是 stackoverflow.com/questions/22136173/,您的使用率可能会显着提高......readlines()csv.reader()
2赞 rasjani 7/26/2023
“A+”将搜索到文件的末尾,如果您尝试从该位置读取,您将一无所获。怀疑您实际上确实尝试过从文件开头开始就使用普通的旧“r”(又名只读)..
1赞 Daraan 7/26/2023
f.seek(0)如果文件不为空,则后跟对我有用。f.readlines()
0赞 amy-elouise 7/26/2023
@rasjani如果我说我试过了,你为什么不认为我试过了?

答:

1赞 Zach Young 7/26/2023 #1

我看到很多刚接触 Python 和 CSV 的人试图使用文件模式追加,他们通常会因此而遇到一些麻烦。

通常,我建议读取源 CSV,修改行,然后将修改后的行写入另一个文件。验证新文件的有效性后,您可以决定如何处理旧文件。

对于读取/写入 CSV,我建议使用 csv 模块的读取器和写入器。

给定 CSV:

Col1,Col2
r1c1,r1c2
r2c1,r2c2
r3c1,r3c2

使用 csv.reader(some_file) 函数为该文件创建行迭代器

with open('input.csv',newline='',encoding='utf-8') as f:
    reader = csv.reader(f)

局部变量读取器将生成完全解码的行。使用 next(reader) 可以一次返回一行:

next(reader)
# ['Col1', 'Col2']
next(reader)
# ['r1c1', 'r1c2']

reader 返回的只是一个字符串列表。

迭代器也可以在 for 循环中使用,如文档所示

for row in reader:
    print(row)

# ['r2c1', 'r2c2']
# ['r3c1', 'r3c2']

请注意,读者从离开的地方继续阅读 next() 语句。此外,现在读取器已经耗尽 - 没有更多的行可以解码。尝试从中读取将引发 StopIteration 异常:

next(reader)
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# StopIteration

要获取所有行并能够遍历它们任意次数,请在创建读取器时使用 list(reader) 将瞬态迭代器转换为永久行列表:

with open('input.csv',newline='',encoding='utf-8') as f:
    reader = csv.reader(f)
    header = next(reader)
    rows = list(reader)

这会将第一行保存到其自己的变量 header 中。其余行将添加到命名行列表中。如果一行是字符串列表,则变量 rows 是字符串列表的列表。

如果要省略标头,请单独调用 next(reader)(没有左手赋值)。读者会尽职尽责地返回标题,但它只会进入空白。

现在,您可以对这些行执行以下操作:

for row in rows:
    name = row[0]
    # do something with name...
    name = name.lower()
    # before saving it back to the list
    row[0] = name

最后,将修改后的行写回 CSV。对我来说,我将始终创建一个新文件:

  1. 我不会销毁原始数据(取回原始数据时真的很痛苦,可能意味着任何步骤,请某人再次发送,甚至不可用)。
  2. 我可以将我得心应手的工作与原来的工作进行比较,以确保我做了正确的事情。
with open('output.csv', 'w', newline='', encoding='utf-8') as f:
    writer = csv.writer(f)
    writer.writerow(header)
    writer.writerows(rows)

一旦你对 output.csv 感到满意,你就可以决定如何处理 input.csv - 保留它,丢弃它,用 output.csv () 覆盖它。os.rename('output.csv', 'input.csv')

祝你好运。:)

评论

1赞 amy-elouise 7/26/2023
谢谢,这信息量很大,让人深思:)
1赞 amy-elouise 7/26/2023 #2

以防万一有人遇到同样的问题,以下是最终对我有用的东西:

if save is True:
     with open('dataset.csv', newline='') as f:
          reader = csv.reader(f)
          header = next(reader)
          lines = list(reader)
          old_line = ()
          newlines = []
          for line in lines:
               if line[0] == name:
                    old_line = line
                    new_line = old_line + additional_data
                    line = new_line
                    newlines.append(line)
               else:
                    newlines.append(line)

      with open('output.csv', 'w') as g:
           writer = csv.writer(g)
           writer.writerow(header)
           writer.writerows(newlines)
           print("Data added successfully.")

与使用该方法相比,这不仅简化了保存过程,而且完全按照我的意愿工作。感谢大家的帮助:).readlines()