2013-10-28 15 views
7

私はcsvファイルを解析するPythonコードをいくつか持っています。現在、データファイルをgzip csvファイルに変更することをベンダーが決定しました。私は最小限で/きれいなコードの変更が何であるか疑問に思っていました。現在の関数:Python "with"文の構文

def load_data(fname, cols=()): 
    ... ... 
    with open(fname) as f: 
     reader = csv.DictReader(f) 
     ... ... 

コードをload_data2()に複製し、with文を完全に動作するように変更したくありません。

with gzip.open(fname) as f: 

withステートメントをどのように除外できますか?

def load_data(fname, cols=()): 
    ... ... 
    if fname.endswith('.csv.gz'): 
     with gzip.open(fname) as f: 
    else: 
     with open(fname) as f: 

     reader = csv.DictReader(f) 
     ... ... # code to parse 

答えて

6

普遍的なアプローチを動的にありますopenerを選択します。必要なときに

openers = { 
    'http': urllib2.urlopen, 
    '.csv.gz': gzip.open 
    '.csv': open 
} 

resource_type = get_resource_type(resource) # determine the type of the resource 

with openers[resource_type](resource) as f: 
    # do stuff ... 

そのように、あなたは痛みを伴わずに、より多くのオープナーを追加することができます。 factory method design patternの別の例を次に示します。

8

あなたは、ファイル名の特性に応じて、別の変数にファイルを開くために使用したい機能を割り当てることによってこれを行うことができます。

opener = gzip.open if fname.endswith('.csv.gz') else open 
with opener(fname) as f: 
    ... # code to parse 
+2

これは、 'with'ステートメントで直接行うこともできます:' 'gzip.open(fname)if fname.endswith( '。csv.gz')else(fname)' f 'として開く – kindall

+0

ありがとう、 ! – fivelements