如何遍历 dic 和 list
How to iterate over dic and list
我有一个包含一堆 .SQL
文件的文件夹,我希望这些文件与 ALL_TAB_COLUMNS
的提取相匹配(只有 TABLE_NAME
和 COLUMN_NAME
列在column_list.csv
)。
我的 objective 是为每个报告使用 tables/columns 的关系,生成如下输出:
sql_file_name.sql | table_name | column_name
似乎当我从第二个嵌套循环移动到第三个嵌套循环时,变量得到 'out of reach',Python (2.7.13)
将它们视为新的:
import os
import csv
path = "./search_files"
folder = os.listdir(path)
search_dict = csv.DictReader(open("column_list.csv"))
for files in folder:
files = os.path.join(path, files)
file = open(files, "r")
sql = file.readlines()
sql = [x.strip() for x in sql] # Remove \n
hit_count = 0
for i in sql:
i = i.upper() # Make SQL code UPPERCASE
print str(hit_count) + ": " + i # i has values here
hit_count = hit_count + 1
for row in search_dict:
print str(hit_count) + ": " + i # i is blank here
hit_count = hit_count + 1
if row['TABLE_NAME'] in i or row['COLUMN_NAME'] in i:
print row['TABLE_NAME'] + " | " + row['COLUMN_NAME']
您的问题是 search_dict
是一个迭代器,您正试图对其进行多次迭代。那是行不通的。第一次到达输入文件末尾后,迭代器将永远为空。
有几种方法可以解决这个问题。最简单的可能是将迭代器中的值转储到列表中:
search_dict = list(csv.DictReader(open("column_list.csv")))
这种方法唯一真正的缺点是,如果您的 CSV 文件很大,它可能会占用大量内存。
或者,您可以 "cheat" 使用迭代器协议。通常引发了 StopIteration
异常的迭代器应该永远持续下去。但是文件是迭代器,可以让你作弊。如果你 seek
文件回到开头,你可以再次遍历它的内容。这 可能 让您继续迭代其他迭代器,这些迭代器从您回绕的文件中获取输入。无法保证这将始终有效。它适用于 csv.reader
和 csv.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
循环创建)也具有误导性。它包含一个文件名,而不是几个文件(复数名称暗示)。
我有一个包含一堆 .SQL
文件的文件夹,我希望这些文件与 ALL_TAB_COLUMNS
的提取相匹配(只有 TABLE_NAME
和 COLUMN_NAME
列在column_list.csv
)。
我的 objective 是为每个报告使用 tables/columns 的关系,生成如下输出:
sql_file_name.sql | table_name | column_name
似乎当我从第二个嵌套循环移动到第三个嵌套循环时,变量得到 'out of reach',Python (2.7.13)
将它们视为新的:
import os
import csv
path = "./search_files"
folder = os.listdir(path)
search_dict = csv.DictReader(open("column_list.csv"))
for files in folder:
files = os.path.join(path, files)
file = open(files, "r")
sql = file.readlines()
sql = [x.strip() for x in sql] # Remove \n
hit_count = 0
for i in sql:
i = i.upper() # Make SQL code UPPERCASE
print str(hit_count) + ": " + i # i has values here
hit_count = hit_count + 1
for row in search_dict:
print str(hit_count) + ": " + i # i is blank here
hit_count = hit_count + 1
if row['TABLE_NAME'] in i or row['COLUMN_NAME'] in i:
print row['TABLE_NAME'] + " | " + row['COLUMN_NAME']
您的问题是 search_dict
是一个迭代器,您正试图对其进行多次迭代。那是行不通的。第一次到达输入文件末尾后,迭代器将永远为空。
有几种方法可以解决这个问题。最简单的可能是将迭代器中的值转储到列表中:
search_dict = list(csv.DictReader(open("column_list.csv")))
这种方法唯一真正的缺点是,如果您的 CSV 文件很大,它可能会占用大量内存。
或者,您可以 "cheat" 使用迭代器协议。通常引发了 StopIteration
异常的迭代器应该永远持续下去。但是文件是迭代器,可以让你作弊。如果你 seek
文件回到开头,你可以再次遍历它的内容。这 可能 让您继续迭代其他迭代器,这些迭代器从您回绕的文件中获取输入。无法保证这将始终有效。它适用于 csv.reader
和 csv.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
循环创建)也具有误导性。它包含一个文件名,而不是几个文件(复数名称暗示)。