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')
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
を使用します。
このようにネストしたブロックを使う
with open(newfile, 'w') as outfile:
with open(oldfile, 'r', encoding='utf-8') as infile:
# your logic goes right here
あなたはあなたのブロックを入れ子にすることができます。このような:
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で説明 のように複数のコンテキストマネージャを持つことができます。それはネスティングよりも良い選択肢であるように私には思えます。
そしてあなたの最後のマイナーな質問のために、リターンは本当の目的には役立ちません。削除します。
時々、あなたは可変量のファイルを開き、それぞれを同じように扱うことを望むかもしれません、あなたはこれを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())