编写了生成一些数据的函数后,我想添加保存它的功能。我最初使用以下代码开始,并使用“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...
[]
不太确定为什么它无法读取这些行?我虽然之前使用过相同的代码来读取这个文件的行,所以我真的很困惑为什么它现在不起作用。
我尝试在代码中添加一些内容,例如
f.seek(0)
,但这没有什么区别。我还尝试将打开功能更改为 'a'
和 'r'
但可惜它无法读取这些行。我搜索了很多关于.readlines()
的帖子,但找不到任何人经历过这个:(我觉得我工作太久了,已经忘记了Python编码的基本原理!
提前致谢<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 新手尝试使用文件模式追加,他们通常会因此陷入一些麻烦。
一般来说,我建议读取源 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 返回的row只是一个字符串列表。
迭代器也可以在 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。对我来说,我总是会创建一个新文件:
我不会销毁原始数据(取回原始数据时真正的痛苦可能意味着要执行许多步骤,好心地请求某人再次发送它,或者甚至无法提供)。
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')
)。
祝你好运。 :)
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()
方法相比,这不仅简化了保存过程,而且它完全按照我想要的方式工作。谢谢大家的帮助:)