끝나지 않는 프로그래밍 일기

1. 파일 입출력(File Input/Output)

오늘은 파일 입출력에 대해서 알아보도록 하겠습니다. 전 강좌에서는 화면에서 출력하고 입력하는 방법을 알아봤다면, 이번에는 파일에 출력하고 입력하는 것을 알아보도록 하겠습니다. 파일을 읽고, 쓰고, 덧붙이는 등 세밀하게 작업을 위해 파이썬에서는 open이란 함수를 지원하는데 이 함수의 기본형은 아래와 같습니다.

파일객체 = open(file, mode)

기본적으로 들어가는 두 인자 중 file이란 인자에는 파일 이름이 이곳에 들어가고, mode에는 파일을 열 때 사용하는 모드를 말합니다. 여기서 파일을 열 때 사용하는 모드란 쓰기 모드, 읽기 모드 등과 같이 파일에 무언가를 쓸때는 쓰기 모드, 무언가를 읽어들일 때는 읽기 모드를 사용합니다. 아래에 mode에 들어갈 수 있는 것을 표로 정리해 두었습니다.

모드

설명

r

읽기 모드 (디폴트)

r+

읽기 + 쓰기 모드

w

쓰기 모드

a

쓰기 + 이어쓰기 모드

t

텍스트 모드 (디폴트)

b

바이너리 모드

위에 있는 모드들은 독립적으로 사용되는게 아니라, 서로 모드를 조합해서 사용이 가능합니다. 예를 들면, 'wb'는 바이너리 쓰기 모드가 되며 'rb'는 바이너리 쓰기 모드가 되는 것입니다. 파일을 쓰기 모드로 개방하여 임의의 문자열을 작성해보도록 할까요? 아래 예제를 보면서 open 함수를 통해 파일을 어떻게 만들고 쓰는지 알아보도록 합시다.

>>> f = open('t.txt', 'w')
>>> f.write('abcdefghijk')
11
>>> f.close()

위 예제의 1행을 보시면 't.txt란 파일을 쓰겠다'라는 의미가 됩니다. 이렇게 파일을 쓰기 모드로 열게 되면, 현재 디렉토리에 t.txt란 파일이 없다면 t.txt 파일을 새로 만들게 됩니다. 만약 이미 존재한다면 내용을 모두 지우고 새로 쓰게 되는 것입니다. 이어서 2행에서는 write란 함수를 통해서 파일에 임의의 문자열을 쓸 수 있는데, 이 write 함수는 말 그대로 파일에 문자열을 쓰고 싶을때 이용하는 함수입니다. 3행에서는 write 함수를 호출하여 몇 바이트나 썼는지 정수로 반환해준 값이 나온 것입니다. 마지막으로 4행에서는 파일의 사용이 모두 끝났으므로 파일 객체를 닫는 close 함수를 호출함으로써 마무리를 하게 됩니다. 


이번에는 방금 쓴 파일을 읽어보도록 하겠습니다.

>>> f = open('t.txt', 'r')
>>> f.read()
'abcdefghijk'
>>> f.close()

위 예제의 1행에서는 't.txt란 파일을 읽겠다'라는 의미가 되며, 2행에서는 read란 함수로 파일을 모두 읽어들인 후, 읽은 데이터를 반환합니다. 3행에서는 close 함수로 파일을 닫습니다. 간단하죠? 이번에는 여러 줄을 파일에 써보도록 하겠습니다. 구구단 중 2단만 간단히 텍스트 파일에 작성해보도록 합시다.

>>> for i in range(1, 10):
	data = "2 * %d = %d\n" % (i, 2 * i)
	f.write(data)	
10
..
11
>>> f.close()

그리고 파일에 우리가 예상한 값이 쓰였는지 확인을 해보도록 합시다. 이번에는 read 함수가 아니라 readline이란 함수를 사용하여 파일을 읽어들여 보도록 하겠습니다. 아래를 한번 봅시다.

>>> f = open('gugudan.txt')
>>> line = f.readline()
>>> while line:
	print(line, end='')
	line = f.readline()
	
2 * 1 = 2
2 * 2 = 4
2 * 3 = 6
2 * 4 = 8
2 * 5 = 10
2 * 6 = 12
2 * 7 = 14
2 * 8 = 16
2 * 9 = 18
>>> f.close()

위 예제에서의 1행에서 mode가 비었는데, 읽기 모드가 기본값이므로 파일 이름만 명시해준 것입니다. 2행에서는 readline 함수를 사용하여 한번에 한줄씩 읽어들일 수 있습니다. 3행에서는 while문으로 반복을 하게 되는데, 이 때 line이 빈 문자열일 경우 즉, 더이상 읽어들인 문자열이 없을 경우에 반복문을 벗어나게 됩니다. 4행에서는 읽어들인 문자열에 이미 \n가 있기 때문에 끝문자(end)를 비워주는 것입니다. 5행에서는 현재 위치에서 다음 줄을 읽어들이기 위함이구요. 정상적으로 결과물이 출력됨을 확인한 후에, 파일 객체인 f를 닫습니다. 이 방법 말고도 또 파일을 읽어들이는 방법이 있는데, readline이 아니라 이번에는 readlines이란 함수를 이용하는 방법입니다. 한번 보시죠.

>>> f = open('gugudan.txt')
>>> lines = f.readlines()
>>> for line in lines:
	print(line, end='')
	
2 * 1 = 2
2 * 2 = 4
2 * 3 = 6
2 * 4 = 8
2 * 5 = 10
2 * 6 = 12
2 * 7 = 14
2 * 8 = 16
2 * 9 = 18
>>> f.close()

위 예제의 2행에서는 readlines 함수를 사용하여 파일의 내용 전체를 줄 단위로 잘라서 리스트에 저장하여, 저장한 리스트를 반환시켜서 lines에 넣습니다. 3~4행에서는 for문을 이용하여 리스트를 순차적으로 읽고 출력하는 것을 보실 수 있습니다. 역시 마지막은 close 함수를 통해 마무리를 짓습니다. 이번에는 파일 입출력에서 빠질 수 없는 tell과 seek 함수에 대해서 보도록 하겠습니다. tell 함수는 현재 파일의 위치를 반환하고, seek 함수는 현재 파일의 위치를 지정한 곳으로 이동시킵니다.

>>> f = open('hangul.txt', 'w')
>>> f.write('가나다\n라마바\n사아자\n차카타\n파하')
18
>>> f.close()

위의 파이썬 코드로 쓰여진 텍스트 파일을 한번 읽어보면서 seek와 tell 함수를 사용하여 보도록 하겠습니다.

>>> f = open('hangul.txt', 'r')
>>> f.tell()
0
>>> f.read()
'가나다\n라마바\n사아자\n차카타\n파하'
>>> f.tell()
36
>>> f.seek(0)
0
>>> f.tell()
0
>>> f.readline()
'가나다\n'
>>> f.tell()
8
>>> f.close()

위 예제의 2행에서는 tell 함수가 사용되었는데, tell 함수의 반환값이 0입니다. 이는 현재 파일의 위치가 0에 있음을 나타내며, 파일 위치는 현재 파일에서 어디까지 읽거나 썼는지를 나타내는 위치입니다. 4행에서 파일에 있는 내용을 모두 읽어들이고, 6행에서 tell 함수를 사용하여 위치를 확인해 보았더니 36이란 값이 나왔습니다. 


그 후에 8행에서 seek 함수를 통해 파일 위치를 0으로 지정하고, 다시 tell 함수를 사용해 위치를 확인해 보았더니 0이란 값이 나왔습니다. 이어서 12행의 readline 함수를 사용한 뒤에, 14행에서 tell 함수를 사용해 보았더니 파일의 위치가 8임을 알 수 있었습니다.