2016-12-17 44 views
0

我主要用於生成器的是處理存儲在遠程服務器上的CSV文件行。它允許我有一致的接口來線性處理存儲在其中的數據。清理尚未完全耗盡的迭代器

現在,我使用paramiko爲了訪問存儲文件的SFTP服務器 - 並且如果您沒有關閉文件本身,paramiko有一個未正確關閉連接的突出問題。我有一個訪問sftp上的單個文件的簡單接口(這顯然是一個僞代碼 - 我省略了連接錯誤處理代碼等)。

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' might be propegation of StopIteration that cause the issue see [PEP 479](https://www.python.org/dev/peps/pep-0479/)... nevermind,I不要以爲我理解你的問題。 –

+0

您是否嘗試過只調用sys.exit()? – pvg

+0

@pvg當然,它的工作原理。問題不在於「如何使其工作」,而是如何正確地釋放不再使用的發生器,因爲它們在我的情況下似乎沒有被正確地垃圾收集。 –

回答

0

這還不是最完美的解決方案,但是我們可以通過在物體包裹發電機蓄客@ tadhg,麥當勞-Jensen的建議:

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連接,但正值讀取所有的行到內存中一次費用。