web-dev-qa-db-ja.com

Pythonの既存のファイルに行を追加します

テキストファイルの最初の行に1行追加する必要がありますが、利用できるオプションは、Pythonで予想されるよりも多くのコード行だけであるように見えます。このようなもの:

f = open('filename','r')
temp = f.read()
f.close()

f = open('filename', 'w')
f.write("#testfirstline")

f.write(temp)
f.close()

簡単な方法はありませんか?さらに、この2つのハンドルの例は、読み取りと書き込み( 'r +')のために単一のハンドルを開くよりも頻繁に表示されます。なぜですか?

64
Nick

Pythonは多くのことを簡単にし、多くの一般的な操作のライブラリとラッパーを含みますが、目標は基本的な真実を隠すことではありません。

ここで直面している基本的な真実は、通常、構造全体を書き換えずに既存のフラット構造にデータを追加することはできないということです。これは言語に関係なく当てはまります。

ファイルハンドルを保存したり、コードを読みにくくしたりする方法がありますが、その多くは他の回答で提供されていますが、基本的な操作を変更するものはありません。読み込んだ既存のデータ。

必ずファイルハンドルを保存してください。ただし、この操作を可能な限り少ないコード行にまとめようとはしないでください。実際、コードの最少数の行を探しに行くことはありません。それはプログラミングではなく難読化です。

80
Nicholas Knight

私は別々の読み取りと書き込みに固執しますが、それぞれをより簡潔に表現できます。

Python2:

with file('filename', 'r') as original: data = original.read()
with file('filename', 'w') as modified: modified.write("new first line\n" + data)

Python3:

with open('filename', 'r') as original: data = original.read()
with open('filename', 'w') as modified: modified.write("new first line\n" + data)

注:file()関数はpython3では使用できません。

58
Karl Knechtel

その他のアプローチ:

with open("infile") as f1:
    with open("outfile", "w") as f2:
        f2.write("#test firstline")
        for line in f1:
            f2.write(line)

または1つのライナー:

open("outfile", "w").write("#test firstline\n" + open("infile").read())

この問題について考える機会をありがとう:)

乾杯

21
Morlock
with open("file", "r+") as f: s = f.read(); f.seek(0); f.write("prepend\n" + s)
9
barti_ddu

これにより、1回の書き込み呼び出しを保存できます。

f.write('#testfirstline\n' + temp)

「r +」を使用する場合、読み取り後および書き込み前にファイルを巻き戻す必要があります。

3
infrared

ここに私が明確で柔軟だと思う3ライナーがあります。 list.insert関数を使用するため、本当にファイルの先頭に追加する場合は、l.insert(0、 'insert_str')を使用します。 Python私が開発中のモジュールに対して実際にこれを行ったとき、 '#--コーディング: utf-8--'行0の文字列。コードは次のとおりです。

f = open(file_path, 'r'); s = f.read(); f.close()
l = s.splitlines(); l.insert(0, 'insert_str'); s = '\n'.join(l)
f = open(file_path, 'w'); f.write(s); f.close()

これは、ファイル全体をメモリに読み込まずにジョブを実行しますが、Windowsでは機能しない場合があります

def prepend_line(path, line):
    with open(path, 'r') as old:
        os.unlink(path)
        with open(path, 'w') as new:
            new.write(str(line) + "\n")
            shutil.copyfileobj(old, new)
2
eug

1つの可能性は次のとおりです。

import os
open('tempfile', 'w').write('#testfirstline\n' + open('filename', 'r').read())
os.rename('tempfile', 'filename')
0
JooMing

私は何かを見ていませんか、または入力ファイル parts (コンテンツ全体ではなく)を読み込むのに十分な大きさのバッファーを使用することはできませんか?ファイルが開いている間、ファイル<->バッファの内容を交換し続けますか?

これは、(特に大きなファイルの場合) whole content in memory を読み取るよりもはるかに効率的ですメモリ内で同じファイルに書き戻すか、さらに悪いことに別のファイルに書き戻します。サンプルスニペットを実装する時間がないのでごめんなさい、後でこれに戻りますが、おそらくあなたはそのアイデアを得るでしょう。

0
Corneliu Zuzu

特定のテキストの後にファイルに追加する場合は、以下の機能を使用できます。

def prepend_text(file, text, after=None):
    ''' Prepend file with given raw text '''
    f_read = open(file, 'r')
    buff = f_read.read()
    f_read.close()
    f_write = open(file, 'w')
    inject_pos = 0
    if after:
        pattern = after
        inject_pos = buff.find(pattern)+len(pattern)
    f_write.write(buff[:inject_pos] + text + buff[inject_pos:])
    f_write.close()

そのため、最初にファイルを開き、読み取り、すべてを1つの文字列に保存します。次に、インジェクションが発生する文字列の文字番号を見つけようとします。次に、1回の書き込みと文字列のスマートインデックスを使用して、挿入されたテキストを含むファイル全体を書き換えることができます。

0
Pithikos