맨 먼저 작성해볼 함수는 프로그램이 종료될 때 유효한 연락처 정보를 파일로 저장하는 store_contact라는 함수입니다. 이 함수는 contact_list라는 리스트를 입력받은 후 해당 리스트에 있는 Contact 인스턴스를 순회하면서 데이터를 파일로 저장합니다.
store_contact 함수는 함수가 호출될 때 먼저 ‘contact_db.txt’라는 이름의 텍스트 파일을 ‘wt’ 모드로 엽니다. 그런 다음 contact_list를 순회하면서 각 인스턴스의 정보를 write 함수를 통해 출력합니다. 이때 출력되는 각 정보가 파일에서 각 라인 단위로 저장되도록 ‘\n’을 사용했습니다. contact_list의 모든 데이터를 파일로 출력했다면 f.close()를 통해 파일을 닫습니다.
파일로 저장하는 기능은 프로그램이 종료될 때 호출하면 되므로 기존에 작성된 run 함수를 수정합니다.
수정된 프로그램을 실행한 후 그림 8.28과 같이 연락처를 하나 입력하고 프로그램을 종료해 봅시다.
그림 8.29와 같이 PyCharm의 프로젝트 화면을 보면 contact_db.txt라는 이름의 파일이 생성된 것을 확인할 수 있습니다.
해당 파일의 이름을 더블클릭하면 그림 8.30과 같이 PyCharm의 에디터 화면에서 생성된 텍스트 파일의 내용을 확인할 수 있습니다. 참고로 contact_db.txt 파일은 프로젝트 소스코드가 존재하는 디렉터리에 생성되는데, PyCharm에서는 이를 프로젝트 뷰에서 바로 보여주기 때문에 프로그램을 작성할 때보다 편리하게 파일 내용을 확인할 수 있습니다.
앞서 프로그램이 종료될 때 유효한 연락처를 파일로 저장하는 기능을 구현했습니다. 이번에는 이와 반대로 이전에 파일로 저장돼 있던 연락처 정보를 프로그램이 시작될 때 불러들이는 기능을 구현해 보겠습니다.
파일로부터 연락처를 로드하는 함수의 이름은 load_contact입니다. 이 함수 역시 contact_list를 인자로 받으며, 함수 내부에서 ‘contact_db.txt’ 파일을 열어서 해당 파일을 라인 단위로 저장된 이름, 전화번호, 이메일, 주소로 읽어 들여 Contact 클래스의 인스턴스를 생성합니다. 그런 다음 생성한 인스턴스를 contact_list에 추가합니다.
def load_contact(contact_list):
f = open("contact_db.txt", "rt")
lines = f.readlines()
num = len(lines) / 4
num = int(num)
for i in range(num):
name = lines[4*i].rstrip('\n')
phone = lines[4*i+1].rstrip('\n')
email = lines[4*i+2].rstrip('\n')
addr = lines[4*i+3].rstrip('\n')
contact = Contact(name, phone, email, addr)
contact_list.append(contact)
f.close()
load_contact 함수는 먼저 readlines 함수를 이용해 파일에 있는 모든 데이터를 읽습니다. 연락처 하나당 4줄의 데이터가 존재하므로 파일에서 읽어 들인 전체 라인 수를 4로 나누어 몇 개의 데이터가 존재하는지 확인합니다. 나눗셈 연산을 수행하면 num 값이 실수가 되는데, 이 값을 int 내장 함수를 사용해 정수형으로 형변환합니다.
for 문에서는 num의 개수만큼 루프를 돌면서 lines 리스트에 저장된 데이터를 읽어 들여 Contact 클래스의 인스턴스를 생성하고 생성한 인스턴스를 contact_list에 추가합니다.
앞서 설명한 것처럼 파일로 저장된 연락처를 불러오는 것은 연락처 관리 프로그램이 실행될 때 이뤄져야 합니다. 따라서 다음과 같이 run 함수가 시작하는 부분에서 load_contact 함수를 호출하면 됩니다.
def run():
contact_list = []
load_contact(contact_list)
while 1:
menu = print_menu()
if menu == 1:
contact = set_contact()
contact_list.append(contact)
elif menu == 2:
print_contact(contact_list)
elif menu == 3:
name = input("Name: ")
delete_contact(contact_list, name)
elif menu == 4:
store_contact(contact_list)
break
예제 8.3은 지금까지 작성한 주소록 프로젝트의 최종 코드입니다. 해당 코드는 파일 입출력 기능을 추가로 수행함으로써 프로그램이 종료되더라도 프로그램이 실행된 시점의 데이터를 하드디스크에 저장할 수 있습니다. 또한 프로그램이 시작될 때 하드디스크에 저장된 파일을 읽어 들여 프로그램이 종료되던 시점의 데이터를 그대로 복원하는 기능을 제공합니다.
class Contact:
def __init__(self, name, phone_number, e_mail, addr):
self.name = name
self.phone_number = phone_number
self.e_mail = e_mail
self.addr = addr
def print_info(self):
print("Name: ", self.name)
print("Phone Number: ", self.phone_number)
print("E-mail: ", self.e_mail)
print("Address: ", self.addr)
def set_contact():
name = input("Name: ")
phone_number = input("Phone Number: ")
e_mail = input("E-mail: ")
addr = input("Address: ")
contact = Contact(name, phone_number, e_mail, addr)
return contact
def print_contact(contact_list):
for contact in contact_list:
contact.print_info()
def delete_contact(contact_list, name):
for i, contact in enumerate(contact_list):
if contact.name == name:
del contact_list[i]
def load_contact(contact_list):
f = open("contact_db.txt", "rt")
lines = f.readlines()
num = len(lines) / 4
num = int(num)
for i in range(num):
name = lines[4*i].rstrip('\n')
phone = lines[4*i+1].rstrip('\n')
email = lines[4*i+2].rstrip('\n')
addr = lines[4*i+3].rstrip('\n')
contact = Contact(name, phone, email, addr)
contact_list.append(contact)
f.close()
def store_contact(contact_list):
f = open("contact_db.txt", "wt")
for contact in contact_list:
f.write(contact.name + '\n')
f.write(contact.phone_number + '\n')
f.write(contact.e_mail + '\n')
f.write(contact.addr + '\n')
f.close()
def print_menu():
print("1. 연락처 입력")
print("2. 연락처 출력")
print("3. 연락처 삭제")
print("4. 종료")
menu = input("메뉴선택: ")
return int(menu)
def run():
contact_list = []
load_contact(contact_list)
while 1:
menu = print_menu()
if menu == 1:
contact = set_contact()
contact_list.append(contact)
elif menu == 2:
print_contact(contact_list)
elif menu == 3:
name = input("Name: ")
delete_contact(contact_list, name)
elif menu == 4:
store_contact(contact_list)
break
if __name__ == "__main__":
run()
예제 8.3 주소록 프로젝트의 최종 코드(소스코드: book/ch08/03.py)
3) 명령 프롬프트에서 프로그램 실행하기
지금까지 PyCharm을 통해 프로그램을 개발하고 동시에 실행해 보면서 프로그램을 작성했습니다. PyCharm을 이용해 프로그램을 작성하면 하드디스크에 파이썬 소스코드 형태로 프로그램이 저장됩니다. 이번 절에서는 윈도우의 명령 프롬프트를 이용해 직접 파이썬 코드를 실행해 보겠습니다.
윈도우에서 명령 프롬프트를 실행하려면 윈도우 시작 버튼을 누른 다음 [실행] → [cmd]를 입력하면 됩니다. 명령 프롬프트가 나타나면 지금까지 작성한 Contact 프로젝트 경로로 이동합니다. 저자의 PC를 기준으로 설명해 드리면 현재 프로젝트 파일은 ‘C:\Users\Jason\PyCharmProjects\Contact’ 에 있습니다. 따라서 다음과 같이 cd(change directory) 명령을 이용해 해당 디렉터리 경로로 이동합니다. 파이썬 프로젝트가 들어있는 곳으로 이동하고 나면 dir 명령어를 입력해 현재 디렉터리에 contact.py라는 파일이 있는지 확인합니다.
Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.
C:\Users\Jason>cd PycharmProjects
C:\Users\Jason\PycharmProjects>cd Contact
C:\Users\Jason\PycharmProjects\Contact>dir
C 드라이브의 볼륨에는 이름이 없습니다.
볼륨 일련 번호: 3E7A-5817
C:\Users\Jason\PycharmProjects\Contact 디렉터리
2016-10-05 오전 08:18 <DIR> .
2016-10-05 오전 08:18 <DIR> ..
2016-10-05 오전 08:15 2,319 contact.py
1개 파일 2,319 바이트
2개 디렉터리 93,350,182,912 바이트 남음
C:\Users\Jason\PycharmProjects\Contact>
cd 명령어를 이용해 정상적으로 프로젝트 경로로 이동했다면 ‘python contact.py’를 입력해 파이썬 프로그램을 실행할 수 있습니다.
C:\Users\Jason\PycharmProjects\Contact>python contact.py
1. 연락처 입력
2. 연락처 출력
3. 연락처 삭제
4. 종료
메뉴선택:
프로그램을 개발하는 과정에서는 PyCharm과 같은 IDE 상에서 파이썬 프로그램을 직접 실행하지만 프로그램 개발이 완료된 후에는 방금 설명한 바와 같이 직접 파이썬 소스코드를 사용해 프로그램을 실행하게 됩니다.