Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

Python linecache 모듈로 텍스트 파일을 줄 단위로 읽는 방법

linecache 모듈이란?

파이썬의 linecache 모듈은 파일의 내용을 줄(line) 단위로 분할하여 메모리에 캐시로 보관하는 기능을 제공합니다. 이 모듈은 리스트 인덱싱 방식으로 원하는 줄을 반환하기 때문에, 파일을 반복해서 열고 매번 전체 내용을 읽어 파싱하는 것보다 훨씬 적은 시간으로 특정 줄에 접근할 수 있습니다.

특히 동일한 파일에서 여러 줄을 반복적으로 조회해야 하는 경우 linecache 모듈이 매우 유용합니다. 파일을 한 번만 읽어 캐시에 저장한 뒤에는 이후 모든 접근이 메모리에서 바로 이루어지기 때문입니다.

테스트 데이터 준비하기

먼저 실습에 사용할 샘플 텍스트를 준비합니다. 아래처럼 Lorem ipsum 더미 텍스트 몇 단락이면 충분하며, 검색 엔진에서 샘플 텍스트를 찾아 그대로 사용해도 좋습니다.

import os
import tempfile

text = """
Lorem ipsum dolor sit amet, causae apeirian ea his, duo cu congue prodesset. Ut epicuri invenire duo, novum ridens eu has, in natum meliore noluisse sea. Has ei stet explicari. No nam eirmod deterruisset, nusquam electram rationibus ad sea, interesset delicatissimi et sit. Purto molestiae cu eum, in per hinc periculis intellegam.

Id porro facete cum. No est veritus detraxit facilisis, sit ea clita decore essent. Ut eam labores fuisset menandri, ex sit brute viderer eleifend, altera argumentum vel ex. Duo at zril sensibus, eu vim ullum assentior, quando possit at his.

Te nam tempor posidonium scripserit, eam mundi reprimique dissentias ne. Vim te soleat offendit democritum. Nam an diam elaboraret, quaeque dissentias an has. Autem legendos dignissim ad vis, sea ex amet petentium reprehendunt, inermis constituam philosophia ne mel. Esse noster lobortis usu ne.

Nec reque postea urbanitas ut, mea in nulla invidunt ocurreret. Ei duo iuvaret numquam. Ferri nemore audire te est, mel et detracto noluisse. Nec eu habeo justo, id pro posse apeirian volutpat. Mea sonet quaestio ne.

Atqui quaeque alienum te vim. Graeco aliquip liberavisse pro ut. Te similique reformidans usu, te mundi aliquando ius. Meis scripta minimum quo no, meis prima fabellas eu eam, laoreet delicata forensibus ut vim. Et quo vocibus mediocritatem, atqui summo an eam.
"""

임시 파일 생성·삭제 함수 만들기

별도의 텍스트 파일을 미리 준비하는 대신, 실행 시점에 임시 파일을 만들고 사용이 끝나면 자동으로 삭제하는 방식을 사용하겠습니다. tempfile.mkstemp()mkdtemp()를 사용하면 임시 파일과 디렉터리를 손쉽게 생성할 수 있습니다.

def make_tempfile():
    """
    기능 : 임시 파일 생성
    mkstemp(), mkdtemp()로 임시 파일과 디렉터리를 생성

    args : None

    return : 임시 파일 이름
    """
    fd, temp_file = tempfile.mkstemp()
    os.close(fd)

    with open(temp_file, 'wt') as f:
        f.write(text)

    return temp_file


def cleanup(temp_file):
    os.unlink(temp_file)

linecache로 특정 줄 읽기

이제 linecache 모듈로 특정 줄을 읽어 보겠습니다. 반드시 기억해야 할 중요한 점은, linecache 모듈의 줄 번호는 리스트처럼 0부터 시작하는 것이 아니라 1부터 시작한다는 것입니다. 일반적인 파이썬 인덱싱 습관과 다르므로 혼동하지 않도록 주의해야 합니다.

import os
import tempfile
import linecache

text = """
Lorem ipsum dolor sit amet, causae apeirian ea his, duo cu congue prodesset. Ut epicuri invenire duo, novum ridens eu has, in natum meliore noluisse sea. Has ei stet explicari. No nam eirmod deterruisset, nusquam electram rationibus ad sea, interesset delicatissimi et sit. Purto molestiae cu eum, in per hinc periculis intellegam.

Id porro facete cum. No est veritus detraxit facilisis, sit ea clita decore essent. Ut eam labores fuisset menandri, ex sit brute viderer eleifend, altera argumentum vel ex. Duo at zril sensibus, eu vim ullum assentior, quando possit at his.

Te nam tempor posidonium scripserit, eam mundi reprimique dissentias ne. Vim te soleat offendit democritum. Nam an diam elaboraret, quaeque dissentias an has. Autem legendos dignissim ad vis, sea ex amet petentium reprehendunt, inermis constituam philosophia ne mel. Esse noster lobortis usu ne.

Nec reque postea urbanitas ut, mea in nulla invidunt ocurreret. Ei duo iuvaret numquam. Ferri nemore audire te est, mel et detracto noluisse. Nec eu habeo justo, id pro posse apeirian volutpat. Mea sonet quaestio ne.

Atqui quaeque alienum te vim. Graeco aliquip liberavisse pro ut. Te similique reformidans usu, te mundi aliquando ius. Meis scripta minimum quo no, meis prima fabellas eu eam, laoreet delicata forensibus ut vim. Et quo vocibus mediocritatem, atqui summo an eam.
"""


def make_tempfile():
    """
    기능 : 임시 파일 생성
    mkstemp(), mkdtemp()로 임시 파일과 디렉터리를 생성

    args : None

    return : 임시 파일 이름
    """
    directory = os.getcwd()
    fd, temp_file = tempfile.mkstemp(dir=directory)
    os.close(fd)

    with open(temp_file, 'wt') as f:
        f.write(text)

    return temp_file


def cleanup(temp_file):
    os.unlink(temp_file)


# ipsum 데이터로 임시 파일 생성
filename = make_tempfile()
print(f"생성된 임시 파일 \n {filename}")

split_line = '\n'

# 원본 문자열에서 직접 해당 줄 가져오기
print(f"\n*** 원본에서 직접 읽은 5번째 줄 \n {text.split(split_line)[4]}")

# linecache 캐시에서 같은 줄 가져오기
print(f"\n*** linecache 캐시에서 읽은 5번째 줄 \n {linecache.getline(filename, 5)}")

# unlink()로 임시 파일 정리
cleanup(filename)

실행 결과

C:\Users\sasan\PycharmProjects\blog\TutorialPoints\Updated_Code\tmpazax_yne

*** 원본에서 직접 읽은 5번째 줄
Id porro facete cum. No est veritus detraxit facilisis, sit ea clita decore essent. Ut eam labores fuisset menandri, ex sit brute viderer eleifend, altera argumentum vel ex. Duo at zril sensibus, eu vim ullum assentior, quando possit at his.

*** linecache 캐시에서 읽은 5번째 줄
Id porro facete cum. No est veritus detraxit facilisis, sit ea clita decore essent. Ut eam labores fuisset menandri, ex sit brute viderer eleifend, altera argumentum vel ex. Duo at zril sensibus, eu vim ullum assentior, quando possit at his.

원본 문자열에서 직접 분할해 얻은 결과와 linecache 캐시에서 가져온 결과가 완전히 동일한 것을 확인할 수 있습니다.

줄 끝 개행 문자(\n) 처리 방식

linecache는 항상 줄 끝의 개행 문자(newline)를 포함하여 반환합니다. 따라서 해당 줄이 비어 있다면 반환값은 개행 문자 하나뿐입니다. 아래 예제로 확인해 보겠습니다.

import linecache

# ipsum 데이터로 임시 파일 생성
filename = make_tempfile()
print(f"생성된 임시 파일 \n {filename}")

# 빈 줄은 개행 문자만 포함하여 반환된다.
print(f"\n*** 텍스트의 전체 줄 수는 13줄이다.")
print("\n*** linecache에서 마지막 줄을 출력하면 개행 문자만 반환된다 \n {!r}".format(linecache.getline(filename, 8)))

cleanup(filename)

실행 결과

C:\Users\sasan\PycharmProjects\blog\TutorialPoints\Updated_Code\tmp352zirvn

*** 텍스트의 전체 줄 수는 13줄이다.

*** linecache에서 마지막 줄을 출력하면 개행 문자만 반환된다
'\n'

마무리

애플리케이션이 파일에 대한 무작위(random) 접근이 필요할 때, linecache를 사용하면 줄 번호만으로 원하는 줄을 손쉽게 읽을 수 있습니다. 다만 파일의 전체 내용이 캐시에 계속 유지되므로, 대용량 파일을 다룰 때는 메모리 사용량에 유의해야 합니다. 캐시를 초기화해야 하는 상황에서는 linecache.clearcache()를 호출하면 됩니다.