web-dev-qa-db-ja.com

Open with Openセメントを使用してファイルを開く方法

Pythonでファイルの入出力をする方法を調べています。ファイル内の名前に対して名前をチェックし、ファイル内の出現箇所にテキストを追加しながら、ファイルから別のファイルに名前のリスト(1行に1つ)を読み取るための次のコードを書きました。コードは動作します。もっとうまくできましたか?

入力ファイルと出力ファイルの両方に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')
174
Disnami

Pythonでは、複数のopen()ステートメントを単一のwithに入れることができます。カンマで区切ってください。あなたのコードは次のようになります。

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ステートメントが導入されたときのPython 2.5またはPython 2.6では、withで複数のopen()項目を使用することはできませんでしたが、Python 2.7およびPython 3.1以降ではサポートされています。

http://docs.python.org/reference/compound_stmts.html#the-with-statementhttp://docs.python.org/release/3.1/reference/compound_stmts.html#the-with - ステートメント

Python 2.5、2.6、または3.0で実行しなければならないコードを書いている場合は、他の答えが示すようにwithステートメントをネストするか、 contextlib.nested を使用します。

270
steveha

このようにネストしたブロックを使う

with open(newfile, 'w') as outfile:
    with open(oldfile, 'r', encoding='utf-8') as infile:
        # your logic goes right here
24
RanRag

あなたはあなたのブロックを入れ子にすることができます。このような:

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)

あなたのコードが例外に遭遇してもoutfileが閉じられることを保証するので、これはあなたのバージョンより良いです。明らかにtry/finallyでそれを行うことができますが、これを行うにはwithが正しい方法です。

あるいは、先ほど学んだように、withステートメント内に @stevehaで説明 のように複数のコンテキストマネージャを持つことができます。それはネスティングよりも良い選択肢であるように私には思えます。

そしてあなたの最後のマイナーな質問のために、リターンは本当の目的には役立ちません。削除します。

10
David Heffernan

時々、あなたは可変量のファイルを開き、それぞれを同じように扱うことを望むかもしれません、あなたはこれをcontextlibで行うことができます

from contextlib import ExitStack
filenames = [file1.txt, file2.txt, file3.txt]

with open('outfile.txt', 'a') as outfile:
    with ExitStack() as stack:
        file_pointers = [stack.enter_context(open(file, 'r')) for file in filenames]                
            for fp in file_pointers:
                outfile.write(fp.read())                   
1
brother-bilo