TL; DR:你能不能可靠迭代通过一个csv对象本身,或使用(如果/不在)对它呢?CSV阅读器重复问题
所以我有一个奇怪的问题。这似乎是间歇性的,但那是因为我不知道发生了什么。我确定有一个真正的原因。
我有以下几点:
import os
import csv
csv_old = 'vendor_old.csv'
csv_new = 'vendor.csv'
csv_sftp = 'vendor_sftp.csv'
def check_vendor_length():
with open(csv_old, 'r') as t_old:
vendor_old = csv.reader(t_old, delimiter = ',')
all_vendor_old = next(vendor_old)
len_vendor_old = len(all_vendor_old)
return len_vendor_old
def check_vendor_old():
with open(csv_old, 'r') as t_old, open(csv_new, 'r') as t_new, open(csv_sftp, 'w', newline = '') as t_sftp:
vendor_old = csv.reader(t_old, delimiter = ',')
vendor_new = csv.reader(t_new, delimiter = ',')
vendor_sftp = csv.writer(t_sftp, delimiter = ',')
all_vendor_old = []
row_vendor_old = next(vendor_old)
row_vendor_old.insert(csv_len, 'action')
all_vendor_old.append(row_vendor_old)
for row_vendor_old in vendor_old:
if row_vendor_old not in vendor_new:
all_vendor_old.append(row_vendor_old + ['remove'])
vendor_sftp.writerows(all_vendor_old)
def check_new():
with open(csv_old, 'r') as t_old, open(csv_new, 'r') as t_new, open(csv_sftp, 'a', newline = '') as t_sftp:
vendor_old = csv.reader(t_old, delimiter = ',')
vendor_new = csv.reader(t_new, delimiter = ',')
vendor_sftp = csv.writer(t_sftp, delimiter = ',')
all_vendor_new = []
row_vendor_new = next(vendor_new)
row_vendor_new.insert(csv_len, 'action')
for row_vendor_new in vendor_new:
all_vendor_new.append(row_vendor_new + ['add'])
vendor_sftp.writerows(all_vendor_new)
所以,第一个功能对新老CSV比较。如果旧版中的行不在新版中,则应将其标记为删除。他们被写入一个(新的)CSV,将SFTP'd给供应商。
第二个函数只取得新CSV中的所有数据并将其附加到SFTP CSV中。
发生的事情是,昨晚生成的SFTP CSV具有所有内容的重复,唯一的区别是首先是“删除”条目,然后是所有这些条目之后的相同行,但是与'添加'而不是'删除'。
但这并不总是发生。在测试中,它按预期工作。没有dups。但由于某种原因,昨晚的SFTP再一次拥有了所有的诀窍。正在处理的CSV只有大约10列,大约5100行。
奇怪的是,当我稍微削减一下,以至于我只用了大约2-300行时,我遇到了同样的问题。
还有额外的代码没有显示,但基本上,在SFTP CSV创建后,旧的CSV已被删除,并且新的CSV被重命名为旧的CSV名称。然后,第二天,当新CSV被转储到目录中时,脚本可以再次运行。冲洗并重复。
我们能确定的是,也许通过CSV对象上迭代最接近(vendor_new = csv.reader(t_new,分隔符= ''))在某种程度上borking过程。所以我做了什么修改的check_vendor_old功能,使新的CSV被读取到一个列表,然后再在for循环检查对新CSV列表旧CSV行:
def check_vendor_old():
with open(csv_old, 'r') as t_old, open(csv_new, 'r') as t_new, open(csv_sftp, 'w', newline = '') as t_sftp:
vendor_old = csv.reader(t_old, delimiter = ',')
vendor_new = csv.reader(t_new, delimiter = ',')
vendor_sftp = csv.writer(t_sftp, delimiter = ',')
all_vendor_old = []
row_vendor_old = next(vendor_old)
row_vendor_old.insert(csv_len, 'action')
all_vendor_old.append(row_vendor_old)
################ NEW STUFF HERE ################
# Create list comprised of new vendor.csv rows
list_vendor_new = []
for row in vendor_new:
list_vendor_new.append(row)
# print(list_vendor_new)
################ NEW STUFF HERE ################
for row_vendor_old in vendor_old:
if row_vendor_old not in list_vendor_new:
all_vendor_old.append(row_vendor_old + ['remove'])
vendor_sftp.writerows(all_vendor_old)
所以,这一切现在似乎按预期工作......但我想我们会看到。
所以我的问题是,是否有什么,我错过了当阅读csv阅读器文档?你能不能可靠遍历csv对象本身,或者使用[if/not in]来对付它?它似乎在测试过程中起作用,但显然昨晚没有按计划进行。
UPDATE
我发现vendor_new.seek(0)
不工作(因为vendor_new
类是_csv.reader
,它没有寻求方法),但t_new
(我打开CSV AS)是_io.TextIOWrapper
,里面确实有寻找方法。
所以我想,如果我是这样做:
def check_vendor_old():
...
for row_vendor_old in vendor_old:
if row_vendor_old not in vendor_new:
all_vendor_old.append(row_vendor_old + ['remove'])
t_new.seek(0)
这可能是更接近我想要的东西。 (如果我真的想与csv.reader对象,而不是一个列表的工作。)
谢谢你。尽管你的回答很有帮助,你能帮我澄清一下吗?假设'vendor_new'对象由5行组成,当我做'如果row_vendor_old不在vendor_new'中时,实际发生了什么?它是否通过'vendor_new'前进一次,然后不重置在vendor_old'循环中的下一个'for row_vendor_old?可以/应该使用'vendor_new.seek(0)'来重置'vendor_new'吗? – thisAaronMdev
它是一个'iterator',它不是'file',它不是'list',它不是任何类型的容器。它只是一个'迭代器',**它所能做的就是向前迈进**。它不能“重置”。如果您需要继续检查其中的内容,请将其转换为适当的容器(就像在您工作的示例中一样)。 – donkopotamus