2016-12-17 11 views
0

私の主な使用方法は、リモートサーバーに格納されたCSVファイルの行を処理することです。それは私がそれらに格納されたデータを線形処理する一貫したインターフェースを持つことを可能にします。完全に使い果たされていないイテレーターのクリーンアップ

ファイルを保存するSFTPサーバーにアクセスするためにparamikoを使用しています。ファイル自体を閉じなかった場合、paramikoは接続を適切に終了しないという顕著な問題があります。

私はsftp上で1つのファイルにアクセスする簡単なインターフェースを持っています(これは明らかに擬似コードです - 接続エラー処理コードなどは省略しています)。

def sftp_read_file(filename): 
     with paramiko.open(filename) as file_obj: 
      for item in csv.reader(file_obj): 
       yield item 

def csv_append_column(iter_obj, col_name, col_val): 
    # header 
    yield next(iter_obj) + (col_name,) 
    for item in iter_obj: 
     yield item + (col_val,) 

のは、私は、行の限られた量のためのスクリプトを実行して、ファイルに実行された変換のセットをテストしたいとしましょう:

def main(): 
    for i, item in enumerate(csv_append_column(sftp_read_file('sftp://...'), 'A', 'B')): 
     print(item) 
     if i > 0 and i % 100 == 0: 
      break 

スクリプトは終了しますが、インタプリタは決してSIGINTなしで終了する。私の可能な解決策は何ですか?

+0

do 'from __future__ import generator_stop'は、[PEP 479](https://www.python.org/dev/peps/pep-0479/)の問題を引き起こしているStopIterationを宣言している可能性があります... nevermind、私私はあなたの問題を理解しているとは思わない。 –

+0

sys.exit()を呼び出してみましたか? – pvg

+0

@pvgもちろん動作します。質問は「それを動作させる方法」ではなく、もはや使用されていないジェネレータを適切に割り振り解除する方法です。なぜなら、私の場合は適切にガベージコレクションされていないようです。 –

答えて

0

これが最もエレガントな解決策ではありませんが、多分私達がオブジェクトに発電機をラップすることにより、@のtadhg-マクドナルド・ジェンセンの提案をオフに構築することができ:

class Stoppable(object): 
    def __init__(self, fn): 
     self.generator = fn 

    def __enter__(self): 
     return self.generator 

    def __exit__(self, type_, value, traceback): 
     self.generator.close() 

そして、このようにそれを使用します。

:私たちはストリーミング用発電機の方法論を使用していない場合
def main(): 
    with Stoppable(sftp_read_file('sftp://...')) as reader: 
     for i, item in enumerate(csv_append_column(reader, 'A', 'B')): 
      print(item) 
      if i > 0 and i % 100 == 0: 
       break 

代わりに、私たちは発電機自体をラップすることができます

def stopit(fn): 
    rg = [ x for x in fn ] 
    for x in rg: 
     yield x 

今、我々はそれが好きで呼び出すことができます。

def main(): 
    for i, item in enumerate(csv_append_column(stopit(sftp_read_file('...')), 'A', 'B')): 
     print(item) 
     if i > 0 and i % 100 == 0: 
      break 

これは確かにブロックが終了し、paramikoとSFTP接続を閉じますが、一度にメモリへのラインの全てを読み取る犠牲にして行います。

関連する問題