CSV阅读器重复问题

时间:2017-08-08 23:15:30

标签: python python-3.x csv

TL; DR:你能否可靠地遍历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的(新的新)CSV的书面形式。

第二个功能只获取新CSV中的所有数据,并将其附加到SFTP CSV。

发生的事情是昨晚生成的SFTP CSV与所有内容都重复,唯一的区别是首先是'删除'条目,然后在所有这些条目之后,相同的行,但是使用“添加”代替“删除”。

但这并不总是发生。在测试中,它按预期工作。没有重复。但出于某种原因,昨晚的SFTP还有所有重复。由此处理的CSV只有大约10列,大约5100行。

奇怪的是,当我把它缩小一点以至于我只用了大约2-300行时,我遇到了同样的问题。

没有显示额外的代码,但基本上,在创建SFTP CSV之后,旧的CSV被删除,新的CSV被重命名为旧的CSV名称。然后,第二天,当新CSV被转储到目录中时,脚本可以再次运行。冲洗并重复。

我们可以确定的最接近的是,可能通过 CSV OBJECT(vendor_new = csv.reader(t_new,delimiter =','))进行迭代,不知怎的。所以我所做的就是修改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]来对付它?它似乎在测试期间起作用,但显然昨晚没有按计划进行。

更新
我发现vendor_new.seek(0)不起作用(因为vendor_new类是_csv.reader,它没有搜索方法),但t_new(我将CSV打开为)是_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对象而不是列表。)

2 个答案:

答案 0 :(得分:0)

您在原始代码中的问题是:

if (!Arrays.asList("yes", "no", "foo", "bar").contains(name_answer)) {

现在,def check_vendor_old(): ... for row_vendor_old in vendor_old: # !!! - this is not doing what you think its doing ... if row_vendor_old not in vendor_new: all_vendor_old.append(row_vendor_old + ['remove']) 不是列表......它是一个迭代器。检查迭代器中是否存在某些内容包括推进它直到找到匹配项。下次执行此操作时,它将从剩余迭代器的位置开始。

举一个例子,考虑一下这个迭代器:

vendor_new

>>> r = (x for x in range(10)) 吗?

5

当然是。但是>>> print(5 in r) True 在其中吗?

3

不......不是,因为在找到>>> print(3 in r) False 时,我们将迭代器推进到5之外。如果将迭代器结晶到列表,问题就会消失:

5

答案 1 :(得分:0)

所以我决定这样做:

    %PDF-1.4
%âãÏÓ
3 0 obj
<</Type /Page
/Parent 1 0 R
/MediaBox [0 0 595.280 841.890]
/TrimBox [0.000 0.000 595.280 841.890]
/Resources 2 0 R
/Group << /Type /Group /S /Transparency /CS /DeviceRGB >> 
/Contents 4 0 R>>
endobj
4 0 obj
<</Filter /FlateDecode /Length 687>>
stream
¡Ï+ëdtüG>KTx´D‰ëE-®Š:øÙ£Þ/íÔÑüÀ3Vƒ­åmzûÙrEë<Å-Å~õÊ2RÏ=ÔÈša牮j»ýqE©{€cSú¡¹S:9RXC q*^w2  E»+`~ÉvÝýwkS§?l¢#çöð«çPÂK.
YÓCR‰˜£…ôÏM°xÑçõ©z+®¢áüØêÂ[ „
-áûþr%²Ü¯6ß8VÅ^jªDA”­öIó¦ì üqœæ6é½òØX
ŽiÙ,hLkv†½uVöüï.h8Rf3cIú±¢õF(½ªêæp´¸·åYÇíÎÊ?xŠä4sð¾]ÆÝ÷µ ›å+DøC›‚6C¾7K¥8܇¹çGÈ`¤ŸçÚ/LO+çôsLÕ    Tß¡‰Ô•‰­Äµ!ôÐç{ê/ºf;Á=¢V€}…=Á£+‰}¨Q„.?øÁ†Ÿúòßê¨Ò€/!Û[Âò#¼«þÏþA?�Uc™–HÄ,‚m¨œ¸„]7P€¿V 9ËŸª*}{1+ŒÛLݧø›‘öw¬PêqÙsé—.ß÷D7ª3Sæºf¶"ºåð~E‹|Ä{mϯaâ´•0|Cw™U};ÊÌ4ÝùfÚE¨ïåsWÒPL6ŸGx™§7þEU\ž7võŸÜHªŽ;>óaPÂs¡ÞÙ˜xüÅÎIhÖD䌷8ó�Äò‚øèF¬BU×Ìt¤³æNµµe÷)LÖ.CõåvÒ4–Sb:wx­lÜ–´ã`    wÇ"c‰>O™Ž-óéúë­AIM¹

在每个循环开始时将def check_vendor_old(): ... for row_vendor_old in vendor_old: t_new.seek(0) ### Added this here if row_vendor_old not in vendor_new: all_vendor_old.append(row_vendor_old + ['remove']) 位置重置为0。我认为它起初并不起作用,因为它需要很长时间才能运行,但这只是因为它在一个CSV中迭代5000行以及在另一个CSV中迭代5000行,而不是像我的一样通过单行原始的坏代码是第一次工作。

所以,我正在给@donkopotamus回答到我的帖子,因为该回复直接回答了我最初的问题,而且我无法找到 my