9. 파이썬 오브젝트 파일
이 포스트를 통해 파이썬 강의에서 마지막으로 소개하게 될 자료형인 파일에 대해서 이야기 해보려고 한다. 셋이라는 자료형이 있긴 하지만 지금까지 배운 것을 토대로 하면 혼자서도 배울 수 있는 부분이다. 또 제목을 오브젝트라고 했는데, 파일은 기본적인 데이터타입은 아니기에 자료형이라는 명칭을 사용하지 않았다.
들어가기전에
이 포스트는 여러분이 파이썬을 설치했고 각자 원하는 IDE를 이용해 파이썬을 개발한다고 가정한다. 대화형(Interactive) 터미널을 사용해도 상관 없다. 혹시 파이썬을 설치하지 않았다면 1.파이썬 설치 및 개발환경 설정 이 포스트에서 파이썬과 파이썬 개발환경을 먼저 셋업하길 바란다. 앞서 말했듯이 반드시 실습 해 보길 바라고 30분 이상 소요하지 말라.
숫자(Numbers) : 12, 24.3, 3+2j, .. (2.파이썬 자료형 숫자)
문자(Strings) : "hello, "world" (3. (1) 파이썬 자료형 문자열, 3.(2) 파이썬 자료형 문자열)
리스트(Lists) : [1, 3, [3, 'hey'], 4] (4. (1) 파이썬 자료형 리스트, 4. (2) 파이썬 자료형 리스트)
딕셔너리(Dictionaries) : { 'name': 'fsoftwareengineer', 'age' : 17} (5. (1) 파이썬 자료형 딕셔너리, 5.(2) 파이썬 자료형 딕셔너리)
튜플(Tuples) : (1, 'a', 4, 'c') (8. 파이썬 자료형 튜플)
파일(Files) : f = open('filename', 'r')
셋(Sets) (집합) : { 1, 4, 5 }
다른 타입들 : Boolean (True/Faluse), types, None, etc
프로그래밍 유닛 타입(Programming unit types) : 함수(Functions), 모듈(Modules), 클래스(Classes)
구현 레벨 타입(Implementational-level types) : 예외(Exception) 등등..
목표
- 파일 (File) ?
- 실습을 위한 텍스트 파일
- 파일 열기/닫기 (File Open/Close)
- 파일 읽기 (File Read)
- 파일 쓰기 (저장) (File Write)
파일 (File) ?
여러분의 컴퓨터에서 열심히 일을 하고 있는 CPU는 주로 메모리와 소통한다. 메모리에 있는 정보를 읽고, 메모리로 다시 정보를 쓴다. 다시 말해 여러분이 추가한 과일 목록들은 전부 메인 메모리에 존재하는 것이다. 그렇다면 왜 프로그램을 껐다 키면 없어지는가? 그것은 여러가지 프로그램들이 동시에 메인 메모리를 사용하기 때문이다. 좀 더 자세히 이야기 해 보자. 여러분 노트북을 살때 메모리8기가, 메모리16기가 라는 말을 들어 봤을 것이다. 바로 그 용량은 "메인 메모리" 용량를 뜻하는 것이다. 즉, 한 시점에서 한번에 사용할 수 있는 메모리의 총 양은 8기가 또는 16기가밖에 안된다는 것이다. 생각해보자. 16기가밖에 안되는 공간에 여러분의 모든 파일과 프로그램을 저장 할 수 있는가? 없다. 용량이 작기 때문에 여기에 모든 것을 저장 할 수 없다. 그래서 보통 메인 메모리에는 "현재 실행중인 프로그램"의 코드와 데이터들만 가지고있고, 프로그램이 종료되면 다른 프로그램을 위해 그 자리를 내준다. 게다가 가장 큰 문제는 이 메인 메모리라는 녀석은 그나마 꽤 빠른 편이지만(그래서 비싸다), 전원이 나가면 메모리 안에 있던 모든 정보가 사라진다. 즉 여러분이 모든 파일과 프로그램을 메모리에 저장 할 수 있더라도, 컴퓨터를 껐다 키는 순간 없어진다는 뜻이다. 그렇기 때문에 우리는 디스크 또는 2차 메모리라는 곳에 파일을 저장한다. 그리고 그 파일을 열어보고 싶을 때 마다, 메인 메모리로 불러온다.
자.... 여러분 바탕화면에 있는 그림파일을 더블클릭하면 어떻게 되는가? 잠시 후에 이미지뷰어같은 프로그램이 뜨면서 그림이 보이지 않는가? 그것은 바로 여러분이 그림파일을 더블클릭 하는 순간, 그 그림파일에 연결된 이미지 뷰어가 실행되고 (코드가 실행되는 것) 그리고 그 코드가 바로 여러분이 클릭한 그림 파일을 메모리로 불러오는 것이다. 바로 오늘 이야기 할 파일과 파일 함수(오퍼레이션)를 이용해서.
실습을 위한 텍스트파일
실습을 위해 텍스트파일을 준비하자. 텍스트파일은 여러분의 프로젝트 디렉토리 바로 안에 넣도록 하자.
파이참을 사용한다면 프로젝트 이름을 마우스 우 클릭 한 후 new > file에서 새 파일을 생성한다.
textfile.txt를 만들고 내부에 apple, banana, orange, mango를 추가했다.
파일 열기 (File Open)
파일을 사용하기 위해서는 일단 파일을 열어야 한다. 파일을 열 때, 2가지 매개변수를 넘겨줘야한다. 첫번째는 파일의 경로이고 두번째는 이 파일을 읽을 것인지 아니면 이 파일에 쓸 것인지 이다. 일단 파일 안의 내용물을 읽고 싶으므로 읽기모드(r)로 파일을 열어보자.
file = open('textfile.txt', 'r')
print(file.name)
file.close() textfile.txt
파일의 이름이 출력되는 것을 확인 할 수 있다. 쓰기모드로 여는 것은 파일 쓰기에서 해 보도록 하겠다. 주의해야 할 점은 파일을 열었다면 반드시 닫아야 한다는것이다. 여러분의 생각에야 알아서 닫힐 것 같지만 시스템(운영체제)입장에서는 처리해야하는 일들이 많다. 그러니 close로 항상 닫아주자.
파일 읽기 (File Read)
파일을 열었다는 것은 여러분이 이 파일의 위치와 모드를 지정하고 여러가지 시스템 레벨의 다른 작업들을 끝냈다는 뜻이다. 그 이후에는 파일을 읽기만 하면 된다. 파일을 읽어보자.
file = open('textfile.txt', 'r')
text = file.read()
print(text)
file.close() apple banana orange mango
위 처럼 파일의 내용이 출력되는 것을 확인 할 수 있다. 주의 할 것은 파일 전체가 하나의 문자열로 저장되었다는 것이다.
file = open('textfile.txt', 'r')
text = file.read(3)
print(text) file.close()
app
몇 바이트(1개의 문자는 1바이트)만 가져오고 싶다면 read안에 가져오고 싶은 바이트의 수를 넣어주면 된다.
file = open('textfile.txt', 'r')
text = file.readline()
print(text)
file.close()
apple
한 줄만 가져오고 싶다면 이렇게 readLine을 사용하면 된다.
file = open('textfile.txt', 'r')
file.readline()
text = file.readline()
print(text)
file.close()
banana
readLine을 두 번 했더니 어떻게 되는가? 그렇다, 두번째 문장인 banana가 나온다. readLine을 한번 할 때마다 커서가 다음줄로 이동하는 효과와 같다. 그러면 전체를 한 줄씩 프린트하려면 어떻게 하면 좋겠는가? 그렇다 반복문을 쓰면 된다.
file = open('textfile.txt', 'r')
while True:
text = file.readline()
if text == None:
break;
print(text) file.close()
apple banana orange mango
이상 한 점이 있다. 여러분 위의 file.read에서는 한줄씩 잘 나왔는데, 얘는 왜 중간에 한 줄이 더 비는가? 여러분 `\n`줄 바꿈 이스케이프 문자에 대해 기억이 나는가? 우리가 텍스트파일에 과일 이름들을 입력 했을 당시, 엔터 또는 리턴키를 이용해 줄 바꿈을 했다. 우리가 엔터/리턴 키를 누를 때 마다 시스템은 `\n`이라는 이스케이프 문자를 입력한다. 윈도우즈는 \r\n일 수도 있다 따라서 위의 텍스트파일 전체를 text에 집어 넣었어도 각 단어의 마지막에 이스케이프 문자가 존재한다. 그래서 별 다른 조치 없이도 줄 바꿈이 되었던 것이다.
이 예제에서 우리는 한 줄씩 가져온다, 그리고 print라는 함수는 원래 출력후 한줄을 뛴다. 따라서 `\n` + print 함수의 한줄 건너 뛰는 현상으로 바로 다음줄이 아닌 다음 다음줄에 그 다음 단어가 나오는 것이다. 믿기 힘들다면 다음을 보자.
file = open('textfile.txt', 'r')
list = []
while True:
text = file.readline()
if len(text) == 0:
break;
list.append(text)
print(list) file.close() ['apple\n', 'banana\n', 'orange\n', 'mango']
여러분.. 줄바꿈 문자가 보이는가? 지금은 우리가 문자열이 아닌 리스트 자체를 출력하는 것이기 때문에 줄바꿈 문자를 볼 수 있다. 이 줄바꿈 문자는 누구에게나 골칫덩이이기 때문에 문자열에서는 이런 이스케이프 문자를 제거할수있는 rstrip이라는 함수를 제공한다. (찾아봐라. 연습문제에서 필요하니.)
file = open('textfile.txt', 'r')
list = file.readlines()
print(list) file.close() ['apple\n', 'banana\n', 'orange\n', 'mango']
다행히도 위와 똑같은 일을 수행하는 함수가 존재한다. readlines라는 함수이다. 사용해보자. 이 함수는 사용하더라도 어차피 반복문을 돌며 줄바꿈 문자를 제거 해 줘야 할 것 같은 예감이 든다.
파일 쓰기 (File Write)
이번에는 쓰기모드로 파일을 열어보자. 새 파일을 만들 것이므로 new_textfile.txt라고 해 보자. 그리고 거기에 1줄을 쓸 것이다.
file = open('new_textfile.txt', 'w')
file.write("chocolate\n")
file.close()
이 코드를 실행 시키는 순간, 파이참 프로젝트 네비게이터 새 파일이 생성 된 것을 확인 할 수 있다.
축하한다! 여러분을 파이썬을 이용해 파일을 만들고 파일에 글도 썼다. 그렇다면 이미 존재하던 파일에도 이렇게 할 수 있을까?
file = open('textfile.txt', 'w') #위에 과일 리스트가 있던 파일 이름
file.write("chocolate\n")
file.close()
textfile.txt를 확인 해 보자. 이럴수가! 어떻게 되었는가..? 전부 사라지고 chocolate하나 남았다. 그렇다 우리는 파일을 완전히 덮어쓰기 해 버린 것이다. 그렇다면 파이썬을 이용해서는 그 밑에 덧붙여 쓸 순 없는것인가?
file = open('textfile.txt', 'a')
file.write("apple\n")
file.write("banana\n")
file.write("orange\n")
file.write("mango")
file.close()
그럴리가 없지 않은가. 밑에 덧붙여 쓰기 위해서는 append의 약자인 a모드를 이용해 열어주면 된다. 이렇게 한 후 4가지 과일을 쓰면 이번엔 chocolate이 없어지지 않고 그 밑에 새 문자열들이 생기는 것을 확인 할 수 있다.
chocolate
apple
banana
orange
mango
writelines를 이용하면 리스트를 통째로 파일에 쓸 수 있다.
file = open('textfile.txt', 'a')
file.writelines(["apple\n", "banana\n", "orange\n", "mango\n"])
file.close()
끝
파일까지 했다면 이제 웬만한 주요 자료형/오프젝트는 다 아는 것이다. 파일을 저장하기 위해 사용하는 디스크와 같은 것들을 "디바이스"라고 부르는데 (윈도우에서는 장치, 장치관리자로 관리) 이런 디바이스들은 대게 open/read/write/close이라는 시스템 콜(System Call, 시스템 함수)을 제공한다. 그래서 파일 하나를 할 수 있다면 나중에 다른 디바이스(예를들어 네트워크 소켓)을 하더라도 지금 했던것 과 비슷하게 이해 할 수 있을 것이다. 시스템콜이나 소켓이 뭔지 몰라도 괜찮다. 그냥 그런게 있다더라 하고 넘어가고 나중에 더 자세히 배우면 된다.
연습 문제
조건문에서 했던 연습문제가 기억나는가? 그 때 당시에는 1. 리스트에 과일 이름 추가, 2. 리스트 출력, 3. 종료 이렇게 3가지 메뉴밖에 없었다. 이제 2개를 더 추가해 보자. 3. 파일에서 읽어오기, 4. 파일에 저장하기이다. 3이나 4를 누르면 또 파일 경로를 입력 받을 수 있고, 그 파일 경로로 읽어오거나 저장 가능해야 한다. 파일 경로를 잘못 입력 했을 경우는 아직 생각하지 말자.
뭘 해야할지 잘 모르겠다면 위의 gif를 참고하길 바란다. 이 프로그램을 짜기 위해서는 최소한 리스트 생성, 입력(insert), 파일 열기, 닫기, 입력, 출력, 반복문 for, 반복문 while 그리고 반복문을 빠져나가기 위한 break를 사용 할 줄 알아야 한다.
위 gif의 예제 소스코드는 깃허브에 있다. 다음 포스트인 함수(function)에서는 함수를 이용해 이 예제 소스코드를 리팩토링(refactoring-간결하고 읽기 쉽게 쓰기)를 할 예정이니 꼭 연습문제를 해 보기 바란다.