【问题标题】:Iterating over CSV reader object in Python在 Python 中迭代 CSV 阅读器对象
【发布时间】:2020-08-08 09:53:13
【问题描述】:

我有两个 CSV 文件,其中一个可能比另一个包含更多的记录。我正在编写一个函数来迭代每个并确定哪些记录在转储中但不是骗子。

我的代码如下:

def update_lib(x, y):
    dump = open(x, newline='')
    libr = open(y, newline='')
    dump_reader = csv.reader(dump)
    for dump_row in dump_reader:
        libr_reader = csv.reader(libr)
        for libr_row in libr_reader:
            if dump_row[0] == libr_row[0]:
                break

我希望这会获取转储 (dump_row) 中的第一行并遍历库 (libr_row) 中的每一行以查看第一个元素是否匹配。如果他们这样做了,那么我想移动到转储中的下一行,如果没有,我最终会做其他事情。

我的问题是 libr_reader 似乎“记住”了它的位置,我无法让它回到 libr 的第一行,即使已经达到 break,因此我希望 libr_reader 是重新发起。我什至尝试过del libr_rowdel libr_reader,但这似乎没有什么不同。我怀疑我误解了迭代器,感谢您提供任何帮助。

【问题讨论】:

    标签: python csv iterator


    【解决方案1】:

    当它粘贴在您的问题中时,您将创建一个 libr_reader 对象每次您在 dump_reader 中迭代一行。

    dump_reader = csv.reader(dump)
    for dump_row in dump_reader:
        libr_reader = csv.reader(libr)
    

    dump_reader 这里只创建一次。假设 dump_reader 有 10 行,您将创建 10 个 libr_reader 实例,它们都来自同一个文件句柄。

    根据我们在 cmets 中的讨论,您知道这一点,但您不知道的是 reader 对象正在处理同一个文件句柄,因此仍位于同一个光标处。

    考虑这个例子:

    >>> import io
    >>> my_file = io.StringIO("""Line 1
    ... Another Line
    ... Finally, a third line.""")
    

    这是创建一个模拟文件对象。现在我将创建一个“LineReader”类。

    >>> class LineReader:
    ...     def __init__(self, file):
    ...         self.file = file
    ...     def show_me_a_line(self):
    ...         print(self.file.readline())
    ... 
    

    如果我在同一个文件上使用 三个 行阅读器,该文件仍然会记住它的位置:

    >>> line_reader = LineReader(my_file)
    >>> line_reader.show_me_a_line()
    Line 1
    
    >>> second_line_reader = LineReader(my_file)
    >>> second_line_reader.show_me_a_line()
    Another Line
    
    >>> third_line_reader = LineReader(my_file)
    >>> third_line_reader.show_me_a_line()
    Finally, a third line.
    

    对于my_file对象,我刚才做的和直接做的没有本质区别。首先,我将通过调用 seek(0) 将文件“重置”到开头:

    >>> my_file.seek(0)
    0
    >>> my_file.readline()
    'Line 1\n'
    >>> my_file.readline()
    'Another Line\n'
    >>> my_file.readline()
    'Finally, a third line.'
    

    你有它。

    所以 TL/DR:文件有光标并记住它们的位置。可以将文件句柄视为记住文件所在位置的东西,是的,但也记住您的程序在文件中的位置。

    【讨论】:

    • 这是有意的(如果不正确),以便每次都尝试“重置” libr_reader。当我最初只创建一次时,行为是相同的。
    • 哦,我明白了。我认为要“重置”它,您可能需要将文件句柄“寻找”回文件的开头。但实际上,如果您有足够的内存,您可能应该将两个文件作为数据结构加载到内存中并使用数据结构。
    • 我明白了,谢谢,您的意思是将这些转换为列表吗?我也有兴趣了解为什么即使重新创建迭代也会记住它的位置......
    • @TomTry 好的,我更新了答案,解释了文件的工作原理。这实际上在 Python、C 或几乎任何编程语言中都是相同的。这有帮助吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-16
    相关资源
    最近更新 更多