[PYTHON] 파이썬으로 거대한 텍스트 파일을 분할하는 방법
PYTHON파이썬으로 거대한 텍스트 파일을 분할하는 방법
거대한 텍스트 파일 (~ 1GB)이 있고 슬프게도 내가 사용하는 텍스트 편집기는 큰 파일을 읽지 않습니다. 그러나 2 ~ 3 부분으로 나누면 괜찮을 것이므로 연습을 위해 파이썬으로 프로그램을 작성하고 싶습니다.
내가 원하는 것은 파일의 크기를 찾고, 그 수를 여러 부분으로 나눈 다음, 각 부분에 대해 청크로 그 부분을 읽고, 파일 이름에 쓰는 것입니다 .nnn 출력 파일을 읽은 다음, 다음 줄 바꿈을하고 그것을 작성한 다음 출력 파일을 닫으십시오. 분명히 마지막 출력 파일은 입력 파일의 끝에 복사합니다.
핵심 파일 시스템과 관련된 부분을 도와 줄 수 있습니까? 파일 크기, 읽기 및 쓰기, 그리고 줄 바꿈?
필자는이 코드를 먼저 테스트 할 것이므로 한 가지가 아닌 한 완전한 대답을 줄 필요가 없다. ;-)
해결법
-
==============================
1.os.stat ()에서 파일 크기와 file.readlines ([sizehint])를 확인하십시오. 이 두 함수는 여러분이 독서 부분에 필요한 모든 것이어야하고 잘하면이 글을 쓰는 법을 알고있다. :)
os.stat ()에서 파일 크기와 file.readlines ([sizehint])를 확인하십시오. 이 두 함수는 여러분이 독서 부분에 필요한 모든 것이어야하고 잘하면이 글을 쓰는 법을 알고있다. :)
-
==============================
2.리눅스에는 분할 명령이있다.
리눅스에는 분할 명령이있다.
split -l 100000 file.txt
동일한 100,000 줄 크기의 파일로 분할됩니다.
-
==============================
3.로깅 라이브러리를 사용하는 또 다른 방법은 다음과 같습니다.
로깅 라이브러리를 사용하는 또 다른 방법은 다음과 같습니다.
>>> import logging.handlers >>> log = logging.getLogger() >>> fh = logging.handlers.RotatingFileHandler("D://filename.txt", maxBytes=2**20*100, backupCount=100) # 100 MB each, up to a maximum of 100 files >>> log.addHandler(fh) >>> log.setLevel(logging.INFO) >>> f = open("D://biglog.txt") >>> while True: ... log.info(f.readline().strip())
파일은 다음과 같이 나타납니다.
이것은 RotatingFileHandler 구현과 일치하는 거대한 로그 파일을 만드는 빠르고 쉬운 방법입니다.
-
==============================
4.이 생성기 방법은 메모리를 날리지 않고 한 줄의 조각을 얻는 (느린) 방법입니다.
이 생성기 방법은 메모리를 날리지 않고 한 줄의 조각을 얻는 (느린) 방법입니다.
import itertools def slicefile(filename, start, end): lines = open(filename) return itertools.islice(lines, start, end) out = open("/blah.txt", "w") for line in slicefile("/python27/readme.txt", 10, 15): out.write(line)
-
==============================
5.파일에 무작위로 액세스하려면 seek () 및 mmap ()을 잊지 마십시오.
파일에 무작위로 액세스하려면 seek () 및 mmap ()을 잊지 마십시오.
def getSomeChunk(filename, start, len): fobj = open(filename, 'r+b') m = mmap.mmap(fobj.fileno(), 0) return m[start:start+len]
-
==============================
6.Ryan Ginstrom의 대답은 정확하지만, (그가 이미 언급 한 것보다) 오래 걸릴 것입니다. 다음은 열린 파일 설명자를 반복적으로 반복하여 itertools.islice에 대한 여러 호출을 우회하는 방법입니다.
Ryan Ginstrom의 대답은 정확하지만, (그가 이미 언급 한 것보다) 오래 걸릴 것입니다. 다음은 열린 파일 설명자를 반복적으로 반복하여 itertools.islice에 대한 여러 호출을 우회하는 방법입니다.
def splitfile(infilepath, chunksize): fname, ext = infilepath.rsplit('.',1) i = 0 written = False with open(infilepath) as infile: while True: outfilepath = "{}{}.{}".format(fname, i, ext) with open(outfilepath, 'w') as outfile: for line in (infile.readline() for _ in range(chunksize)): outfile.write(line) written = bool(line) if not written: break i += 1
-
==============================
7.wc 및 split (각 맨 페이지 참조)을 사용하여 원하는 효과를 얻을 수 있습니다. bash에서 :
wc 및 split (각 맨 페이지 참조)을 사용하여 원하는 효과를 얻을 수 있습니다. bash에서 :
split -dl$((`wc -l 'filename'|sed 's/ .*$//'` / 3 + 1)) filename filename-chunk.
같은 라인 카운트 (마지막으로 반올림 오류가 있음)의 3 부분을 생성하며, filename-chunk.00은 filename-chunk.02로 명명됩니다.
-
==============================
8.나는 프로그램을 작성 했으므로 제대로 작동하는 것 같다. Kamil Kisiel 덕분에 시작되었습니다. (FileSizeParts () 함수는 여기에 표시되지 않음) 나중에 나는 더 빠른 버전인지보기 위해 바이너리를 읽는 버전을하는 것에 다가 갈지도 모른다.
나는 프로그램을 작성 했으므로 제대로 작동하는 것 같다. Kamil Kisiel 덕분에 시작되었습니다. (FileSizeParts () 함수는 여기에 표시되지 않음) 나중에 나는 더 빠른 버전인지보기 위해 바이너리를 읽는 버전을하는 것에 다가 갈지도 모른다.
def Split(inputFile,numParts,outputName): fileSize=os.stat(inputFile).st_size parts=FileSizeParts(fileSize,numParts) openInputFile = open(inputFile, 'r') outPart=1 for part in parts: if openInputFile.tell()<fileSize: fullOutputName=outputName+os.extsep+str(outPart) outPart+=1 openOutputFile=open(fullOutputName,'w') openOutputFile.writelines(openInputFile.readlines(part)) openOutputFile.close() openInputFile.close() return outPart-1
-
==============================
9.이제 어떤 크기의 파일도 여러 조각으로 나눌 수있는 파이피 모듈을 사용할 수 있습니다. 이것 좀 봐
이제 어떤 크기의 파일도 여러 조각으로 나눌 수있는 파이피 모듈을 사용할 수 있습니다. 이것 좀 봐
https://pypi.org/project/filesplit/
-
==============================
10.사용법 - split.py 파일명 splititsinkb
사용법 - split.py 파일명 splititsinkb
import os import sys def getfilesize(filename): with open(filename,"rb") as fr: fr.seek(0,2) # move to end of the file size=fr.tell() print("getfilesize: size: %s" % size) return fr.tell() def splitfile(filename, splitsize): # Open original file in read only mode if not os.path.isfile(filename): print("No such file as: \"%s\"" % filename) return filesize=getfilesize(filename) with open(filename,"rb") as fr: counter=1 orginalfilename = filename.split(".") readlimit = 5000 #read 5kb at a time n_splits = filesize//splitsize print("splitfile: No of splits required: %s" % str(n_splits)) for i in range(n_splits+1): chunks_count = int(splitsize)//int(readlimit) data_5kb = fr.read(readlimit) # read # Create split files print("chunks_count: %d" % chunks_count) with open(orginalfilename[0]+"_{id}.".format(id=str(counter))+orginalfilename[1],"ab") as fw: fw.seek(0) fw.truncate()# truncate original if present while data_5kb: fw.write(data_5kb) if chunks_count: chunks_count-=1 data_5kb = fr.read(readlimit) else: break counter+=1 if __name__ == "__main__": if len(sys.argv) < 3: print("Filename or splitsize not provided: Usage: filesplit.py filename splitsizeinkb ") else: filesize = int(sys.argv[2]) * 1000 #make into kb filename = sys.argv[1] splitfile(filename, filesize)
-
==============================
11.이것은 나를 위해 일했다.
이것은 나를 위해 일했다.
import os fil = "inputfile" outfil = "outputfile" f = open(fil,'r') numbits = 1000000000 for i in range(0,os.stat(fil).st_size/numbits+1): o = open(outfil+str(i),'w') segment = f.readlines(numbits) for c in range(0,len(segment)): o.write(segment[c]+"\n") o.close()
-
==============================
12.또는 wc와 split의 파이썬 버전 :
또는 wc와 split의 파이썬 버전 :
lines = 0 for l in open(filename): lines += 1
그런 다음 첫 번째 행 / 3을 한 파일로, 다음 행 / 3을 다른 파일로 읽는 코드
-
==============================
13.수입을위한 파일 크기 한도가 8MB이고 수신하는 파일이 훨씬 크기 때문에 csv 파일을 Dynamics CRM으로 가져 오기 위해 분할해야한다는 요구 사항이있었습니다. 이 프로그램은 사용자가 FileNames 및 LinesPerFile을 입력 한 다음 지정된 파일을 요청 된 행 수로 분할합니다. 나는 그것이 얼마나 빨리 작동하는지 믿을 수 없다!
수입을위한 파일 크기 한도가 8MB이고 수신하는 파일이 훨씬 크기 때문에 csv 파일을 Dynamics CRM으로 가져 오기 위해 분할해야한다는 요구 사항이있었습니다. 이 프로그램은 사용자가 FileNames 및 LinesPerFile을 입력 한 다음 지정된 파일을 요청 된 행 수로 분할합니다. 나는 그것이 얼마나 빨리 작동하는지 믿을 수 없다!
# user input FileNames and LinesPerFile FileCount = 1 FileNames = [] while True: FileName = raw_input('File Name ' + str(FileCount) + ' (enter "Done" after last File):') FileCount = FileCount + 1 if FileName == 'Done': break else: FileNames.append(FileName) LinesPerFile = raw_input('Lines Per File:') LinesPerFile = int(LinesPerFile) for FileName in FileNames: File = open(FileName) # get Header row for Line in File: Header = Line break FileCount = 0 Linecount = 1 for Line in File: #skip Header in File if Line == Header: continue #create NewFile with Header every [LinesPerFile] Lines if Linecount % LinesPerFile == 1: FileCount = FileCount + 1 NewFileName = FileName[:FileName.find('.')] + '-Part' + str(FileCount) + FileName[FileName.find('.'):] NewFile = open(NewFileName,'w') NewFile.write(Header) NewFile.write(Line) Linecount = Linecount + 1 NewFile.close()
-
==============================
14.다음은 subprocess를 사용하여 큰 파일을 분할하는 데 사용할 수있는 python 스크립트입니다.
다음은 subprocess를 사용하여 큰 파일을 분할하는 데 사용할 수있는 python 스크립트입니다.
""" Splits the file into the same directory and deletes the original file """ import subprocess import sys import os SPLIT_FILE_CHUNK_SIZE = '5000' SPLIT_PREFIX_LENGTH = '2' # subprocess expects a string, i.e. 2 = aa, ab, ac etc.. if __name__ == "__main__": file_path = sys.argv[1] # i.e. split -a 2 -l 5000 t/some_file.txt ~/tmp/t/ subprocess.call(["split", "-a", SPLIT_PREFIX_LENGTH, "-l", SPLIT_FILE_CHUNK_SIZE, file_path, os.path.dirname(file_path) + '/']) # Remove the original file once done splitting try: os.remove(file_path) except OSError: pass
당신은 그것을 외부 적으로 부를 수 있습니다 :
import os fs_result = os.system("python file_splitter.py {}".format(local_file_path))
하위 프로세스를 가져 와서 프로그램에서 직접 실행할 수도 있습니다.
이 접근 방식의 문제점은 높은 메모리 사용률입니다. 하위 프로세스는 프로세스와 크기가 동일한 메모리 풋 프린트로 포크를 만들고 프로세스 메모리가 이미 무거울 경우 실행 시간 동안 두 배가됩니다. os.system에서도 마찬가지입니다.
거대한 파일을 테스트하지는 않았지만 느린 속도가 될 것이지만 메모리에 더 가깝습니다.
CHUNK_SIZE = 5000 def yield_csv_rows(reader, chunk_size): """ Opens file to ingest, reads each line to return list of rows Expects the header is already removed Replacement for ingest_csv :param reader: dictReader :param chunk_size: int, chunk size """ chunk = [] for i, row in enumerate(reader): if i % chunk_size == 0 and i > 0: yield chunk del chunk[:] chunk.append(row) yield chunk with open(local_file_path, 'rb') as f: f.readline().strip().replace('"', '') reader = unicodecsv.DictReader(f, fieldnames=header.split(','), delimiter=',', quotechar='"') chunks = files.yield_csv_rows(reader, CHUNK_SIZE) for chunk in chunks: if not chunk: break # Do something with your chunk here
from https://stackoverflow.com/questions/291740/how-do-i-split-a-huge-text-file-in-python by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] super ()와 superclass를 직접 호출하는 것의 차이점 (0) | 2018.11.22 |
---|---|
[PYTHON] 파이썬 요청이 내 URL을 백분율로 인코딩하는 것을 방지하려면 어떻게해야합니까? (0) | 2018.11.22 |
[PYTHON] 파이썬으로 MTP USB 장치에 접근하는 법 (0) | 2018.11.22 |
[PYTHON] matplotlib로 numpy datetime64 플롯 (0) | 2018.11.22 |
[PYTHON] 수레에 isdigit 사용하기? (0) | 2018.11.22 |