2017-09-08 17 views
0

.SQLのファイルを束ねたフォルダがあり、これはALL_TAB_COLUMNSTABLE_NAMECOLUMN_NAMEの列はcolumn_list.csvにしかありません)の抽出と一致したいファイルです。私が二から三番目のネストされたループに移動したときに変数が外の」得たものと思わ
sql_file_name.sql | table_name | column_namedicとリストを繰り返す方法

:よう

私の目的は、出力を生成し、各レポートのために使用されるテーブル/列の関係を持つことです「リーチ、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'] 
+0

好奇心、出力を貼り付けることはできますか?私はあなたのSQLファイルにいくつかの空の行があると思わ... – kaza

+1

もちろんです。 '455:CASE LSZ55EXCC2 = '05' を '07' ELSE LSZ55EXCC2端、 1456: ''、 1457:IMLITM、 1458:LSZ55TABC、 1459:LSZ55COMPこれは、最初の印刷の出力からの抽出物であります、 1460:LSZ55AENT、 1461:LSZ55MENT、 1462:0、 1463: 'これはsecound一つからなる : ' 6469: 6470: 6471: 6472: 6473: 6474: ' 最後のプリントは出力されません – Fdiang

+0

ちょっと待ってください、それは可能ですあなたの 'search_dict'は空です!あなたの出力の外観。したがって、 'column_list.csv'が適切であることを確認してください。 'column_list.csv'をcatして最初の数行を編集できますか? – kaza

答えて

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: 
      #... 

別のアプローチは、単にあなたが内側のループを起動するたびに、ファイルを再度開くことであろう。

ルーピングの問題とは関係ないもう1つの提案:ファイルを閉じる際に少し注意する必要があります。これは、withステートメントを使用すると、Pythonで簡単に行うことができます。 var = open(filename)のようなものではなく、with open(filename) as var:を使用し、そのファイルを使用するすべてのコードをその下のブロックにインデントします。インデントされたブロックを終了すると、ファイルは自動的に閉じられます(例外のために終了しても)。私の例では、上記のファイルを開くのあなたの現在のスタイルを保ったが、私は自分のコードのためにそれらを書いていた場合、私が書きたい:

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 

     #... 

そして最後に1:

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)バージョン提案:より良い変数名を使用してください。この問題の混乱の一部は、search_dictという名前のためでした。その名前は、それが単一の辞書を含むべきであるように聞こえる。しかし、それはコード内に実際にあったものではありません(実際にはイテレータとして使用していたcsv.DictReaderインスタンスでした)。同様に、あなたのfiles変数(最も外側のforループによって作成された)も誤解を招きます。それは、複数のファイル(複数の名前が示唆する)ではなく、単一のファイル名と一致します。

+0

私は' search_dict'を通常のように動作させると思います'dict'。あなたは、何回でも何回も繰り返すことができます。「シーク(0)」する必要はありません。 – kaza

関連する問題