web-dev-qa-db-ja.com

Python 1つの大きなファイルに指定された順序で複数のファイルを追加する

最大8つの個別のPythonプロセスが共有フォルダに一時ファイルを作成します。次に、制御プロセスがすべての一時ファイルを特定の順序で1つの大きなファイルに追加するようにしたいと思います。これをOSにとらわれないシェルレベルで行う最も速い方法は?

16
Martlark

単純なファイルIOを使用するだけ:

# tempfiles is a list of file handles to your temp files. Order them however you like
f = open("bigfile.txt", "w")
for tempfile in tempfiles:
    f.write(tempfile.read())

それは、OSにとらわれない程度のものです。それもかなり単純で、パフォーマンスは他のものを使用するのと同じくらい良いはずです。

29
Rafe Kettler

あるファイルを別のファイルに追加するためのシェルレベルのコマンドを認識していません。しかし、 'pythonレベル'で追加するのは簡単なので、python開発者はそれをライブラリに追加する必要があるとは思いませんでした。

解決策は、追加する一時ファイルのサイズと構造によって異なります。それらがすべて小さく、それぞれをメモリに読み取っても構わない場合、Rafe Kettlerからの回答(彼の回答からコピーされ、以下で繰り返されます)は、最小限のコードで仕事をします。

# tempfiles is an ordered list of temp files (open for reading)
f = open("bigfile.txt", "w")
for tempfile in tempfiles:
    f.write(tempfile.read())

ファイルをメモリに完全に読み込むことができない場合、または適切な解決策でない場合は、各ファイルをループして断片的に読み込みます。一時ファイルに、メモリに個別に読み込むことができる改行で終了する行が含まれている場合は、次のようにすることができます

# tempfiles is an ordered list of temp files (open for reading)
f = open("bigfile.txt", "w")
for tempfile in tempfiles:
    for line in tempfile
        f.write(line)

または、常に機能するもの-バッファーサイズを選択して、ファイルを断片的に読み取ることもできます。

# tempfiles is an ordered list of temp files (open for reading)
f = open("bigfile.txt", "w")
for tempfile in tempfiles:
    while True:
        data = tempfile.read(65536)
        if data:
            f.write(data)
        else:
            break

入力/出力 tutorial には多くの良い情報があります。

8
CptJeanLuc

Rafeの答えには、適切な開閉ステートメントが欠けていました。

# tempfiles is a list of file handles to your temp files. Order them however you like
with open("bigfile.txt", "w") as fo:
     for tempfile in tempfiles:
          with open(tempfile,'r') as fi: fo.write(fi.read())

ただし、ビッグファイルの内容をソートする場合、このメソッドは、1つ以上の一時ファイルの最後の行のEOL形式が異なるインスタンスをキャッチしないため、奇妙なソート結果が発生することに注意してください。この場合、読み取り時に一時ファイルの行を削除してから、一貫性のあるEOL行をビッグファイルに書き込む(つまり、追加のコード行を含める)必要があります。

6
ksed
import os
str = os.listdir("./")

for i in str:
    f = open(i)
    f2 = open("temp.txt", "a")
    for line in f.readlines():
        f2.write(line)

上記のコードを使用して、現在のディレクトリにあるすべてのファイルからすべてのコンテンツを読み取り、temp.txtファイルに保存できます。

3
Sumit Naik

fileinput を使用:

with open("bigfile.txt", "w") as big_file:
    with fileinput.input(files=tempfiles) as inputs:
        for line in inputs:
            big_file.write(line)

これは、big_fileに書き込む前にファイル全体をメモリに読み込む必要がないため、@ RafeKettlerの回答よりもメモリ効率が高くなります。

1
Peter Wood

これを試して。これは非常に高速であり(行単位よりもはるかに高速であり、VM大きなファイルのスラッシュ)を引き起こさないはずです)、CPython 2.x、CPython 3を含む、ほぼすべてで実行する必要があります.x、Pypy、Pypy3、およびJython。また、OSに大きく依存しない必要があります。また、ファイルエンコーディングについては想定していません。

#!/usr/local/cpython-3.4/bin/python3

'''Cat 3 files to one: example code'''

import os

def main():
    '''Main function'''
    input_filenames = ['a', 'b', 'c']

    block_size = 1024 * 1024

    if hasattr(os, 'O_BINARY'):
        o_binary = getattr(os, 'O_BINARY')
    else:
        o_binary = 0
    output_file = os.open('output-file', os.O_WRONLY | o_binary)
    for input_filename in input_filenames:
        input_file = os.open(input_filename, os.O_RDONLY | o_binary)
        while True:
            input_block = os.read(input_file, block_size)
            if not input_block:
                break
            os.write(output_file, input_block)
        os.close(input_file)
    os.close(output_file)

main()

省略した1つの(自明ではない)最適化があります。適切なブロックサイズについては何も想定せず、ランダムなものの束を使用し、ランダム化をゆっくりとバックして、適切なものに集中します(「シミュレーテッドアニーリング」と呼ばれることもあります)。 ")。しかし、実際のパフォーマンス上の利点がほとんどないため、これははるかに複雑です。

Os.writeに戻り値を追跡させ、部分的な書き込みを再開させることもできますが、これは、(非終端)* ixシグナルを受信することを期待している場合にのみ必要です。

1
user1277476

複数のファイルから1つの大きなファイルにデータをコピーするシンプルで効率的な方法。その前に、ファイルの名前を(int)に変更する必要があります。 1,2,3,4 ... etc、コード:

#Rename Files First

import os

path = 'directory_name'
files = os.listdir(path)
i = 1
for file in files:
    os.rename(os.path.join(path, file), os.path.join(path, str(i)+'.txt'))

    i = i+1
# Code For Copying Data from Multiple files

import os

i = 1
while i<50:

    filename = i
    for filename in os.listdir("directory_name"):

        # %s is your filename # .txt is file extension 
        f = open("%s.txt" % i,'r') 
        fout = open("output_filename", "a")

    for line in f:
        fout.write(line)
    i += 1
0
Injamul Islam

Python 3にはfileinputクラスもあります。これはこのような状況に最適です。

0
MikeTheTall

8年後に別の回答を追加するのは少し愚かで、多くの回答がありますが、「ファイルに追加」というタイトルでここにたどり着き、バッファリングされた読み取り/書き込みで既存のバイナリファイルに追加するための適切な解決策が見つかりませんでした。 。

だからここにそれを行う基本的な方法があります:

def append_file_to_file(_from, _to):
    block_size = 1024*1024
    with open(_to, "ab") as outfile, open(_from, "rb") as infile:
        while True:
            input_block = infile.read(block_size)
            if not input_block:
                break
            outfile.write(input_block)

このビルディングブロックを前提として、以下を使用できます。

for filename in ['a.bin','b.bin','c.bin']:
    append_file_to_file(filename, 'outfile.bin')
0
ishahak

このコードでは、入出力ファイルのパスと名前を指定でき、そのパスに最終的な大きなファイルを作成します。

import os

dir_name = "Your_Desired_Folder/Goes_Here"    #path
input_files_names = ["File1.txt", "File2.txt", "File3.txt"]     #input files
file_name_out = "Big_File.txt"     #choose a name for the output file
file_output = os.path.join(dir_name, file_name_out)
fout = open(file_output, "w")

for tempfile in input_files_names:
    inputfile = os.path.join(dir_name, tempfile)
    fin = open(inputfile, 'r')
    for line in fin:
        fout.write(line)

fin.close()    
fout.close()
0
mah65