如何迭代dic和list

时间:2017-09-08 23:32:52

标签: python python-2.7 text-analysis

我有一个包含大量.SQL个文件的文件夹,我希望这些文件与ALL_TAB_COLUMNS的提取相匹配(仅TABLE_NAMECOLUMN_NAME列在{{ 1}})。

我的目标是为每个报告使用表/列的关系,生成如下输出:
column_list.csv

似乎当我从第二个嵌套循环移动到第三个嵌套循环时,变量“无法触及”,sql_file_name.sql | table_name | column_name将它们视为新的:

Python (2.7.13)

1 个答案:

答案 0 :(得分:1)

您的问题是search_dict是一个迭代器,并且您尝试多次迭代它。这不起作用。在第一次到达输入文件的末尾之后,迭代器将永远保持为空。

有几种方法可以解决这个问题。最简单的可能是将迭代器中的值转储到列表中:

search_dict = list(csv.DictReader(open("column_list.csv")))

这种方法唯一真正的缺点是,如果您的CSV文件很大,它可能会占用大量内存。

或者,您可以使用迭代器协议“欺骗”一点。通常,引发StopIteration异常的迭代器应该会继续这样做。但文件是迭代器,让你作弊。如果您将文件seek重新开始,则可以再次迭代其内容。这个可以让你继续迭代从你倒带的文件中获取输入的其他迭代器。无法保证这始终有效。它适用于csv.readercsv.DictReader,但不适用于用纯Python编写的生成器函数。

所以这是一种可以调整代码的方法:

search_file = open("column_list.csv")        # keep a reference to this file for later
search_dict = csv.DictReader(search_file)

for files in folder:
    #...
    for i in sql:
        #...

        search_file.seek(0)                  # ensure we're at the start of the file
        for row in search_dict:
            #...

另一种方法是每次启动内循环时重新打开文件。

与循环问题无关的另一个建议:关闭文件可能会更加小心。如果使用with语句,这在Python中很容易实现。使用var = open(filename)而不是执行with open(filename) as var:之类的操作,并将使用该文件的所有代码缩进到其下的块中。退出缩进块时,文件将自动关闭(即使由于异常而退出)。我上面的示例保留了您当前打开文件的样式,但如果我是为自己的代码编写它们,我会写:

with open("column_list.csv") as search_file:
    search_dict = list(csv.DictReader(search file))

# rest of the code is not indented extra

seek(0)版本:

with open("column_list.csv") as search_file:   # the whole code is indented under this block
    search_dict = csv.DictReader(search_file)

    for files in folder:    # files is a really misleading variable name
        files = os.path.join(path, files)
        with open(files, "r") as file:
            sql = file.readlines()  # only a single line needs to be indented extra this time

        #...

最后一个建议:使用更好的变量名称。此问题令人困惑的部分原因是名称search_dict。该名称听起来应该包含一个字典。但这不是它在代码中的实际情况(它实际上是一个csv.DictReader实例,您将其用作迭代器)。同样,您的files变量(由最外面的for循环创建)也具有误导性。它包含一个文件名,而不是几个文件(复数名称表示)。