복붙노트

[PYTHON] 파이썬으로 거대한 텍스트 파일을 분할하는 방법

PYTHON

파이썬으로 거대한 텍스트 파일을 분할하는 방법

거대한 텍스트 파일 (~ 1GB)이 있고 슬프게도 내가 사용하는 텍스트 편집기는 큰 파일을 읽지 않습니다. 그러나 2 ~ 3 부분으로 나누면 괜찮을 것이므로 연습을 위해 파이썬으로 프로그램을 작성하고 싶습니다.

내가 원하는 것은 파일의 크기를 찾고, 그 수를 여러 부분으로 나눈 다음, 각 부분에 대해 청크로 그 부분을 읽고, 파일 이름에 쓰는 것입니다 .nnn 출력 파일을 읽은 다음, 다음 줄 바꿈을하고 그것을 작성한 다음 출력 파일을 닫으십시오. 분명히 마지막 출력 파일은 입력 파일의 끝에 복사합니다.

핵심 파일 시스템과 관련된 부분을 도와 줄 수 있습니까? 파일 크기, 읽기 및 쓰기, 그리고 줄 바꿈?

필자는이 코드를 먼저 테스트 할 것이므로 한 가지가 아닌 한 완전한 대답을 줄 필요가 없다. ;-)

해결법

  1. ==============================

    1.os.stat ()에서 파일 크기와 file.readlines ([sizehint])를 확인하십시오. 이 두 함수는 여러분이 독서 부분에 필요한 모든 것이어야하고 잘하면이 글을 쓰는 법을 알고있다. :)

    os.stat ()에서 파일 크기와 file.readlines ([sizehint])를 확인하십시오. 이 두 함수는 여러분이 독서 부분에 필요한 모든 것이어야하고 잘하면이 글을 쓰는 법을 알고있다. :)

  2. ==============================

    2.리눅스에는 분할 명령이있다.

    리눅스에는 분할 명령이있다.

    split -l 100000 file.txt

    동일한 100,000 줄 크기의 파일로 분할됩니다.

  3. ==============================

    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. ==============================

    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. ==============================

    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. ==============================

    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. ==============================

    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. ==============================

    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. ==============================

    9.이제 어떤 크기의 파일도 여러 조각으로 나눌 수있는 파이피 모듈을 사용할 수 있습니다. 이것 좀 봐

    이제 어떤 크기의 파일도 여러 조각으로 나눌 수있는 파이피 모듈을 사용할 수 있습니다. 이것 좀 봐

    https://pypi.org/project/filesplit/

  10. ==============================

    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. ==============================

    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. ==============================

    12.또는 wc와 split의 파이썬 버전 :

    또는 wc와 split의 파이썬 버전 :

    lines = 0
    for l in open(filename): lines += 1
    

    그런 다음 첫 번째 행 / 3을 한 파일로, 다음 행 / 3을 다른 파일로 읽는 코드

  13. ==============================

    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. ==============================

    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
    
  15. from https://stackoverflow.com/questions/291740/how-do-i-split-a-huge-text-file-in-python by cc-by-sa and MIT license