2017-04-30 15 views
0

これらの行が処理されるのと同時にファイルから行を読み取る方法はありますか?読書と処理はお互いに別々に行われるでしょう。データが読み取られると、それは処理のために与えられるので、処理の速さに関係なく読み取りは常に行われます。ファイルと処理ラインから同時に1行ずつ読む?

+0

別のスレッドで読み込みを行い、 'threading.Queue'を使ってデータをメインスレッドに渡すことができます。 – tdelaney

+0

あなたは何を達成しようとしていますか?スピードの向上? –

答えて

1

「同時に」とは何を意味しているかによって異なります。あなたが必ずしも複数のスレッド、緑色のスレッド、またはイベントベースのコードのウサギの穴を塞ぐことを望んでいないと仮定しましょう。そして、あなたはきれいにラインの読みを分離し、それらのラインをフィルタリング/処理し、ビジネスの論理。

これはイテレータとジェネレータで簡単に実現できます(後者は特別な種類の繰り返し可能です)。 open()呼び出しから返されたfileオブジェクトは、それ自体イテレータとして使用可能であるため、これは非常に簡単です。あなたがそのフィルタリングのいくつかを組み合わせることができたものの/

f = open('file-with-myriads-of-lines.txt', 'r') 

# strip away trailing whitespace (including the newline) 
lines_stripped = (line.rstrip() for line in f) 

# remove trailing "#" comments (note: ignores potential quoting) 
lines_without_comment = (line.partition('#')[0] for line in lines_stripped) 

# remove remaining surrounding whitespace 
lines_cleaned = (line.strip() for line in lines_without_comment) 

# filter out (now) empty lines 
lines_with_content = (line for line in lines_cleaned if line) 

for line in lines_with_content: 
    # your business logic goes here 
    print("Line: {}".format(line)) 

(、案の定、反復可能なの一種である)ジェネレータ式のこの単純な連鎖そのプレフィルター読み出し線を考えてみましょう1つのジェネレータ式にマングリングしたり、forループの中に入れたりすると、タスクがきれいに分離され、チェーンにジェネレータを並べ替えたり、削除したり追加したりすることで、

これは、ビジネスロジックforループで消費されるたびに、必要に応じて各行を読み込み、処理します(別の場所の別の関数で取り除くこともできます)。 は、すべての行を先読みしません。また、は、すべての中間結果を含む中間リストを作成しません。これは、リスト内包表記とは対照的です。リスト内包表記は、かっこの代わりに角かっこで書かれています。

あなたも読みやすさ、カプセル化と保守性を高めるために、関数の形で名前を処理する各単位を与えることができます。もちろん、

def strip_trailing_whitespace(iterable): 
    return (line.rstrip() for line in iterable) 

def remove_trailing_comments(iterable): 
    return (line.partition('#')[0] for line in iterable) 

# ... 


def preprocess_lines(iterable): 

    iterable = strip_trailing_whitespace(iterable) 
    iterable = remove_trailing_comments(iterable) 
    # ... 

    return iterable 


def business_logic(iterable): 
    for line in iterable: 
     # your business logic here 
     print("Line: {}".format(line)) 


def main(): 
    with open('file-with-myriads-of-lines.txt', 'r') as f: 
     iterable = preprocess_lines(f) 
     business_logic(iterable) 


if __name__ == '__main__': 
    main() 

そして、各ラインのあなたの前処理がより複雑になる場合がジェネレータ式の内側に使用可能であるものよりも、あなたは単にyield文または式を使用して、カスタムジェネレータ関数にこれを拡張することができます。他に

def remove_trailing_comments(iterable): 
    """Remove #-comments that are outside of double-quoted parts.""" 

    for line in iterable: 
     pos = -1 
     while True: 
      pos = line.find('#', pos + 1) 
      if pos < 0: 
       break # use whole line 

      if line[:pos].count('"') % 2 == 0: 
       # strip starting from first "#" that's not inside quotes 
       line = line[:pos] 
       break 

     yield line 

すべてが同じまま。

関連する問題