Python의 내장 open() 함수는 하나의 파일을 읽기/쓰기 모드로 열어 해당 파일에 대한 입출력 작업을 수행합니다. 하지만 여러 파일을 한 번에 일괄 처리해야 한다면 Python 표준 라이브러리의 fileinput 모듈을 사용하는 것이 좋습니다. 이 모듈은 파일들을 순차적으로 순회(iterate)할 수 있는 Fileinput 클래스를 제공하며, 같은 목적을 위한 다양한 헬퍼 함수도 함께 정의하고 있습니다.
fileinput.input() 함수
이 모듈의 기본 인터페이스는 input() 함수입니다. 이 함수는 Fileinput 클래스의 인스턴스를 반환합니다.
fileinput.input(files, inplace, mode)
files 매개변수에는 하나 이상의 파일 이름을 지정합니다. 각 파일은 제너레이터처럼 동작하며 for 루프를 통해 순회할 수 있습니다. 파일의 각 줄은 Python 콘솔에 출력됩니다.
>>> for line in fileinput.input('data.txt'):
print(line)files 매개변수에는 여러 파일로 구성된 튜플을 전달할 수도 있습니다. 이 경우 파일들의 내용이 차례대로 하나씩 출력됩니다.
>>> for line in fileinput.input(files=('a.txt', 'b.txt')):
print(line)with 문과 함께 사용하기
Fileinput 클래스는 컨텍스트 관리자(context manager)이므로 with 문과 함께 사용할 수 있습니다. 이렇게 하면 코드 블록이 끝난 후 자동으로 리소스가 정리되어 더 안전합니다.
>>> with fileinput.input(files=('a.txt', 'b.txt')) as f:
for line in f:
print(line)주요 함수 정리
fileinput 모듈에는 아래와 같은 함수들이 정의되어 있습니다.
| 번호 | 함수 및 설명 |
|---|---|
| 1 | filename() 현재 읽고 있는 파일의 이름을 반환합니다. |
| 2 | fileno() 파일 디스크립터(file descriptor) 정수를 반환합니다. |
| 3 | lineno() 읽고 있는 파일의 줄 번호를 반환합니다. 이 번호는 여러 파일에 걸쳐 누적된 값입니다. |
| 4 | filelineno() 현재 파일 기준의 줄 번호만 반환합니다. |
| 5 | isfirstline() 현재 파일의 첫 번째 줄을 읽고 있으면 True를, 그렇지 않으면 False를 반환합니다. |
줄 번호와 함께 내용 출력하기
다음 코드는 파일의 각 줄 앞에 줄 번호를 붙여 출력합니다.
>>> for line in fileinput.input('books.py'):
print('{}->{}'.format(fileinput.filelineno(), line))위 코드의 실행 결과 예시는 다음과 같습니다.
1->import sqlite3
2->conn = sqlite3.connect('c:/python36/books.db')
3->cursor = conn.cursor()
4->cursor.execute("SELECT * from books;")
5->print(cursor.fetchall())glob()으로 폴더 내 여러 파일 처리하기
아래 코드는 폴더 안의 각 파일 이름을 먼저 출력한 뒤, 그 파일의 줄들에 번호를 붙여 출력합니다. 이 프로그램에서는 glob() 함수가 사용되었는데, 이 함수는 현재 경로에서 와일드카드 패턴과 일치하는 파일 목록을 리스트로 반환합니다. 예를 들어 glob('*.py')는 현재 폴더에서 확장자가 .py인 모든 파일의 리스트를 반환하며, 이 리스트가 fileinput.input() 함수의 files 매개변수로 전달됩니다.
import fileinput, glob, sys
for line in fileinput.input(glob.glob("*.py")):
if fileinput.isfirstline():
print(fileinput.filename(), '>')
sys.stdout.write("{}.{}".format(fileinput.filelineno(), line))여기서 isfirstline() 함수의 역할에 주목할 필요가 있습니다. 새로운 파일의 순회가 시작되면 이 함수가 True를 반환하고, fileinput.filename() 함수가 반환한 파일 이름이 먼저 출력된 후 번호가 붙은 줄들이 표시됩니다. 실행 결과 예시는 다음과 같습니다.
1.py >
1.a = 10
2.b = 20
3.print ('addition=',a+b)
hello.py >
1.x = 10
2.y = 20
3.z = x+y
4.print ("x+y=",z)inplace 매개변수
fileinput.input() 함수의 inplace 매개변수는 기본적으로 False입니다. 이 값을 True로 설정하면 입력 파일에 직접 쓰기(write)가 가능해집니다. 즉, 파일을 읽으면서 동시에 그 내용을 원본에 바로 수정할 수 있습니다.
예를 들어 'msg.txt' 파일에 다음과 같은 텍스트가 있다고 가정해 보겠습니다.
Hello Python. Good morning
다음 코드는 fileinput 모듈로 파일을 열고(inplace=True), 그 내용을 원본 파일에 바로 수정합니다.
>>> for line in fileinput.input(files='msg.txt', inplace=True):
line = line.replace('morning', 'evening')
sys.stdout.write(line)실행 후 'msg.txt' 파일을 열어 보면 변경된 내용이 적용되어 있는 것을 확인할 수 있습니다.