35

次を含むreally_big_file.txtというテキストファイルがあります。

line 1
line 2
line 3
line 4
...
line 99999
line 100000

really_big_file.txt をそれぞれ 300 行の小さなファイルに分割する Python スクリプトを書きたいと思います。たとえば、small_file_300.txt には行 1 ~ 300 が含まれ、small_file_600 には行 301 ~ 600 が含まれるというように、大きなファイルのすべての行を含むのに十分な小さなファイルが作成されるまで続きます。

Pythonを使用してこれを達成する最も簡単な方法についての提案をいただければ幸いです

4

10 に答える 10

52
lines_per_file = 300
smallfile = None
with open('really_big_file.txt') as bigfile:
    for lineno, line in enumerate(bigfile):
        if lineno % lines_per_file == 0:
            if smallfile:
                smallfile.close()
            small_filename = 'small_file_{}.txt'.format(lineno + lines_per_file)
            smallfile = open(small_filename, "w")
        smallfile.write(line)
    if smallfile:
        smallfile.close()
于 2013-04-30T01:35:50.863 に答える
35

itertoolsハタのレシピを使用:

from itertools import zip_longest

def grouper(n, iterable, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx
    args = [iter(iterable)] * n
    return zip_longest(fillvalue=fillvalue, *args)

n = 300

with open('really_big_file.txt') as f:
    for i, g in enumerate(grouper(n, f, fillvalue=''), 1):
        with open('small_file_{0}'.format(i * n), 'w') as fout:
            fout.writelines(g)

各行をリストに保存するのとは対照的に、この方法の利点は、イテラブルを行ごとに処理するため、それぞれsmall_fileを一度にメモリに保存する必要がないことです。

この場合の最後のファイルは になりますsmall_file_100200が、までしかないことに注意してくださいline 100000。これは、グループ サイズが均等に分割されないため、書き込む行が残っていないときに、ファイルに何もfillvalue=''書き出さないために発生します。私のように最初に名前を付けるのではなく、一時ファイルに書き込んでから名前を変更することで、これを修正できます。これを行う方法は次のとおりです。

import os, tempfile

with open('really_big_file.txt') as f:
    for i, g in enumerate(grouper(n, f, fillvalue=None)):
        with tempfile.NamedTemporaryFile('w', delete=False) as fout:
            for j, line in enumerate(g, 1): # count number of lines in group
                if line is None:
                    j -= 1 # don't count this line
                    break
                fout.write(line)
        os.rename(fout.name, 'small_file_{0}.txt'.format(i * n + j))

今回はfillvalue=Noneと各行を調べて をチェックしNoneます。それが発生すると、プロセスが終了したことがわかっているので、フィラーをカウントしないように1から減算してからファイルを書き込みます。j

于 2013-04-29T23:31:46.337 に答える
2
import csv
import os
import re

MAX_CHUNKS = 300


def writeRow(idr, row):
    with open("file_%d.csv" % idr, 'ab') as file:
        writer = csv.writer(file, delimiter=',', quotechar='\"', quoting=csv.QUOTE_ALL)
        writer.writerow(row)

def cleanup():
    for f in os.listdir("."):
        if re.search("file_.*", f):
            os.remove(os.path.join(".", f))

def main():
    cleanup()
    with open("large_file.csv", 'rb') as results:
        r = csv.reader(results, delimiter=',', quotechar='\"')
        idr = 1
        for i, x in enumerate(r):
            temp = i + 1
            if not (temp % (MAX_CHUNKS + 1)):
                idr += 1
            writeRow(idr, x)

if __name__ == "__main__": main()
于 2015-06-25T19:48:18.743 に答える
2
lines_per_file = 300  # Lines on each small file
lines = []  # Stores lines not yet written on a small file
lines_counter = 0  # Same as len(lines)
created_files = 0  # Counting how many small files have been created

with open('really_big_file.txt') as big_file:
    for line in big_file:  # Go throught the whole big file
        lines.append(line)
        lines_counter += 1
        if lines_counter == lines_per_file:
            idx = lines_per_file * (created_files + 1)
            with open('small_file_%s.txt' % idx, 'w') as small_file:
                # Write all lines on small file
                small_file.write('\n'.join(stored_lines))
            lines = []  # Reset variables
            lines_counter = 0
            created_files += 1  # One more small file has been created
    # After for-loop has finished
    if lines_counter:  # There are still some lines not written on a file?
        idx = lines_per_file * (created_files + 1)
        with open('small_file_%s.txt' % idx, 'w') as small_file:
            # Write them on a last small file
            small_file.write('n'.join(stored_lines))
        created_files += 1

print '%s small files (with %s lines each) were created.' % (created_files,
                                                             lines_per_file)
于 2013-04-30T00:21:05.687 に答える
0

650000行のファイルでも同じことをしなければなりませんでした。

列挙インデックスと整数 div it (//) をチャンク サイズで使用します

その番号が変更されたら、現在のファイルを閉じて新しいファイルを開きます

これは、フォーマット文字列を使用した python3 ソリューションです。

chunk = 50000  # number of lines from the big file to put in small file
this_small_file = open('./a_folder/0', 'a')

with open('massive_web_log_file') as file_to_read:
    for i, line in enumerate(file_to_read.readlines()):
        file_name = f'./a_folder/{i // chunk}'
        print(i, file_name)  # a bit of feedback that slows the process down a

        if file_name == this_small_file.name:
            this_small_file.write(line)

        else:
            this_small_file.write(line)
            this_small_file.close()
            this_small_file = open(f'{file_name}', 'a')
于 2018-11-28T05:07:39.817 に答える