读取同一个 csv 文件时,嵌套 for 循环在 python 中不起作用

Nested for loop doesn't work in python while reading a same csv file

我是 python 的初学者,并试图通过谷歌搜索找到解决方案。但是,我找不到任何我想要的解决方案。

我想用 python 做的是对数据进行预处理,以查找关键字并从大型 csv 文件中获取包含关键字的所有行。

并且嵌套循环以某种方式经历了 just once 然后它没有经历 second loop

下面显示的代码是我从 csv 文件中查找关键字并写入文本文件的代码的一部分。

def main():
   #Calling file (Directory should be changed)
   data_file = 'dataset.json'
   #Loading data.json file
   with open(data_file, 'r') as fp:
       data = json.load(fp)

       #Make the list for keys    
       key_list = list(data.keys())
       #print(key_list)
   preprocess_txt = open("test_11.txt", "w+", -1, "utf-8")
   support_fact = 0

   for i, k in enumerate(key_list):
       count = 1
       #read csv, and split on "," the line  
       with open("my_csvfile.csv", 'r', encoding = 'utf-8') as csvfile:
           reader = csv.reader(csvfile)
           #The number of q_id is 2
           #This is the part that the nested for loop doesn't work!!!!!!!!!!!!!!!!!!!!!!!!!!!!
           if len(data[k]['Qids']) == 2:
               print("Number 2")
               for m in range(len(data[k]['Qids'])):
                   print(len(data[k]['Qids']))
                   q_id = [data[k]['Qids'][m]]
                   print(q_id)
                   for row in reader: #--->This nested for loop doesn't work after going through one loop!!!!!
                       if all([x in row for x in q_id]):
                           print("YES!!!")
                           preprocess_txt.write("%d %s %s %s\n" % (count, row[0], row[1], row[2]))
                               count += 1

以上代码的详细信息,

首先,它从 data.json 文件中提取所有键,然后将这些键放入列表(key_list).

其次,我使用all([x in row for x in q_id])方法检查包含关键字(q_id)的每一行。

然而,正如我在上面的代码中评论的那样,当 data[k]['Qids'] 的长度为 2 时,它会在第一个循环中正确打印出 YES!!!,但不会打印出 YES!!! 在第二个循环中,这意味着它不会进入 for row in reader 循环,即使该 csv 文件包含关键字。

打印图如下,

我做错了什么..?或者我应该为代码添加什么才能使其正常工作..?

谁能帮帮我..?

感谢观看!

我相信你的 reader 变量只包含你的 csv 文件的第一行,因此 for row in reader 只执行一次。

尝试:

with open("my_csvfile.csv", newline='', 'r', encoding = 'utf-8') as csvfile:

newline=''就是上面介绍的新参数。

参考:https://docs.python.org/3/library/csv.html#id3

Quote: "如果 csvfile 是一个文件对象,它应该用 newline=''

打开

举个例子,假设我有一个如下所示的 CSV 文件:

foods.csv

beef,stew,apple,sauce
apple,pie,potato,salami
tomato,cherry,pie,bacon

和下面的代码,这是为了模拟您当前代码的结构:

def main():
    import csv

    keywords = ["apple", "pie"]

    with open("foods.csv", "r") as file:
        reader = csv.reader(file)

        for keyword in keywords:
            for row in reader:
                if keyword in row:
                    print(f"{keyword} was in {row}")

        print("Done")

main()

期望的结果是,对于我的关键字列表中的每个关键字,如果该关键字存在于我的 CSV 文件的某一行中,我将在屏幕上打印一个字符串 - 指示该关键字在哪一行发生了。

但是,这里是实际输出:

apple was in ['beef', 'stew', 'apple', 'sauce']
apple was in ['apple', 'pie', 'potato', 'salami']
Done
>>> 

它能够在文件中找到关键字 apple 的两个实例,但没有找到 pie!那么,给出了什么?

问题

file 句柄(在您的例子中是 csvfile)产生一次它的内容,然后它们被消耗掉。我们的 reader 对象环绕文件句柄并消耗其内容,直到它们被耗尽,此时将没有剩余行可从文件中读取(内部文件指针已前进到末尾),并且内部for循环不会执行第二次。

解决方法

在外部 for 循环的每次迭代后使用 seek 将内部文件指针移动到开头,或者将文件内容一次读入列表或类似集合,然后迭代改为列表:

更新代码:

def main():
    import csv

    keywords = ["apple", "pie"]

    with open("foods.csv", "r") as file:
        contents = list(csv.reader(file))

        for keyword in keywords:
            for row in contents:
                if keyword in row:
                    print(f"{keyword} was in {row}")

        print("Done")

main()

新输出:

apple was in ['beef', 'stew', 'apple', 'sauce']
apple was in ['apple', 'pie', 'potato', 'salami']
pie was in ['apple', 'pie', 'potato', 'salami']
pie was in ['tomato', 'cherry', 'pie', 'bacon']
Done
>>>