2012-02-14 14 views
113

私はPythonでファイルの入出力を行う方法を見ています。私は、ファイル内の名前に対して名前をチェックし、ファイル内の出現箇所にテキストを追加しながら、ファイルから別のファイルに名前のリスト(1行に1つ)を読み込む次のコードを書いた。コードは機能します。それはもっとうまくいくだろうか?open with文を使ってファイルを開く方法

入力ファイルと出力ファイルの両方にwith open(...ステートメントを使用したかったのですが、それらが同じブロック内にある可能性はわかりません。つまり、一時的な場所に名前を格納する必要があります。

def filter(txt, oldfile, newfile): 
    '''\ 
    Read a list of names from a file line by line into an output file. 
    If a line begins with a particular name, insert a string of text 
    after the name before appending the line to the output file. 
    ''' 

    outfile = open(newfile, 'w') 
    with open(oldfile, 'r', encoding='utf-8') as infile: 
     for line in infile: 
      if line.startswith(txt): 
       line = line[0:len(txt)] + ' - Truly a great person!\n' 
      outfile.write(line) 

    outfile.close() 
    return # Do I gain anything by including this? 

# input the name you want to check against 
text = input('Please enter the name of a great person: ')  
letsgo = filter(text,'Spanish', 'Spanish2') 
+0

?あなたはこれによって何を意味するのか説明できますか? 'フィルタ()'である[組み込み関数](https://docs.python.org/2/library/functions.html#filter)ので、あなたはおそらく、あなたの関数に別の名前を選択する必要があることを –

+2

注意。 – Tom

+0

@Tomは名前空間内の関数が組み込み関数をオーバーライドしていますか? – UpTide

答えて

195

Pythonは単一withで複数open()文を置くことができます。あなたはそれらをカンマ区切りにします。あなたのコードは次のようになります。

def filter(txt, oldfile, newfile): 
    '''\ 
    Read a list of names from a file line by line into an output file. 
    If a line begins with a particular name, insert a string of text 
    after the name before appending the line to the output file. 
    ''' 

    with open(newfile, 'w') as outfile, open(oldfile, 'r', encoding='utf-8') as infile: 
     for line in infile: 
      if line.startswith(txt): 
       line = line[0:len(txt)] + ' - Truly a great person!\n' 
      outfile.write(line) 

# input the name you want to check against 
text = input('Please enter the name of a great person: ')  
letsgo = filter(text,'Spanish', 'Spanish2') 

そして、いや、あなたはあなたの関数の最後で明示的returnを置くことによって何かを得ることはありません。 returnを使用して早期に終了することはできますが、最後に終了していれば、機能は終了せずに終了します。 (値を返す関数ともちろん、あなたが返すように値を指定するreturnを使用しています。)

withで複数のopen()のアイテムを使用するにはwith文が導入された時にはPython 2.5でサポートされている、またはPythonの2.6ではなかったです、 Python 2.7およびPython 3.1以降でサポートされています。

http://docs.python.org/reference/compound_stmts.html#the-with-statement http://docs.python.org/release/3.1/reference/compound_stmts.html#the-with-statement

あなたは他の答えが提案またはcontextlib.nestedを使用するとしてPython 2.5、2.6または3.0、巣にwithのステートメントを実行する必要があり、コードを記述している場合。 「私は一時的な場所に名前を格納する必要があるだろうという意味」

8

あなたのブロックをネストすることができます。このように:あなたはあなたのコードは、例外が発生した場合でも、outfileが閉鎖されることを保証するため

with open(newfile, 'w') as outfile: 
    with open(oldfile, 'r', encoding='utf-8') as infile: 
     for line in infile: 
      if line.startswith(txt): 
       line = line[0:len(txt)] + ' - Truly a great person!\n' 
      outfile.write(line) 

これはあなたのバージョンよりも優れています。明らかにtry/finallyでこれを行うことができますが、withがこれを行う正しい方法です。

それとも、私がちょうど学んだとして、あなたはdescribed by @stevehaとしてwith文で複数のコンテキストマネージャを持つことができます。それはネスティングよりも良い選択肢に思えます。

そして、あなたの最後のマイナーな問題のために、リターンが本当の目的を果たしていません。私はそれを削除します。

+0

ありがとう、非常に。私はそれを試して、あなたが答えを受け入れるようにします。 – Disnami

+0

もう一度ありがとうございます。私が受け入れる前に7つのミントを待たなければならない。 – Disnami

+5

@Disnamiあなたが正しい答えを受け入れるようにしてください(そしてこれはこれではありません!);-) –

18

使用このようなネストされたブロックを、

with open(newfile, 'w') as outfile: 
    with open(oldfile, 'r', encoding='utf-8') as infile: 
    #your logic goes here 
関連する問題