我有一个包含大量.SQL
个文件的文件夹,我希望这些文件与ALL_TAB_COLUMNS
的提取相匹配(仅TABLE_NAME
和COLUMN_NAME
列在{{ 1}})。
我的目标是为每个报告使用表/列的关系,生成如下输出:
column_list.csv
似乎当我从第二个嵌套循环移动到第三个嵌套循环时,变量“无法触及”,sql_file_name.sql | table_name | column_name
将它们视为新的:
Python (2.7.13)
答案 0 :(得分:1)
您的问题是search_dict
是一个迭代器,并且您尝试多次迭代它。这不起作用。在第一次到达输入文件的末尾之后,迭代器将永远保持为空。
有几种方法可以解决这个问题。最简单的可能是将迭代器中的值转储到列表中:
search_dict = list(csv.DictReader(open("column_list.csv")))
这种方法唯一真正的缺点是,如果您的CSV文件很大,它可能会占用大量内存。
或者,您可以使用迭代器协议“欺骗”一点。通常,引发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
循环创建)也具有误导性。它包含一个文件名,而不是几个文件(复数名称表示)。