특정 파일을 열어 저장된 데이터를 읽거나 특정 데이터를 특정 파일에 저장해야 하는 일이 매우 빈번하게 발생한다.
예를 들어 test.txt 라는 파일명을 가진 텍스트파일을 생성하고자 할 때 다음과 같이 한다.
주의: 현재 파이썬이 실행되는 폴더에 test.txt 파일이 없음을 확인하고 시작하도록 한다.
예를 들어 ipython에서는 터미널 명령어인 ls를 실행하면 현재 폴더에 들어 있는 파일들을 확인할 수 있다.
이미 있다면 파일을 옮기거나 파일명을 변경하도록 한다.
터미널 명령어는 파이썬 함수가 아니라, 윈도우 커맨드 창이나, 리눅스 또는 맥용 셸 창에서 사용되는 명령어이다. python은 기본적으로 터미널 명령어를 지원하지 않지만 ipython과 spyder는 지원한다.
In [1]:
ls
In [2]:
f = open('test.txt', 'w')
open 함수는 지정된 파일명을 가진 파일을 생성하고 파일의 위치를 리턴한다.'w' 인자는 쓰기 전용으로 파일을 생성한다는 의미이며 모드(mode)라 부른다.test.txt 파일이 존재하면 기존의 내용을 삭제하고 빈 파일로 만들어 파일을 연다.'w', 읽기 모드 'r', 추가 모드 'a' 세 종류가 있다. file 자료형이다.
In [3]:
type(f)
Out[3]:
file 클래스에는 파일의 내용을 어떻게 읽을지, 다룰지 등에 대한 많은 메소드가 포함되어 있다.
여기서는 write, readlines, readline, read, close, seek 메소도의 활용법을 살펴본다.
In [4]:
dir(f)
Out[4]:
In [5]:
f.write("first line\nsecond line")
'\n'은 줄바꿈을 의미한다. 즉 Enter 키를 눌러 줄바꾸기를 한 것과 동일한 효과를 갖는다.
따라서 위 코드는 두 줄을 test.txt 파일에 입력하는 것을 나타낸다. 입력 내용은 다음과 같다.
first line
second line
In [6]:
f.close()
파일을 닫으면 더 이상 파일 내용을 확인할 수 없다.
예를 들어 열려 있는 파일의 경우 read 메소드를 이용하여 내용을 확인할 수 있어야 하는데
이미 test.txt 파일을 닫았기 때문에 오류가 발생한다.
In [7]:
f.read()
ipython이 실행중일 경우 터미널 명령어인 cat를 사용하여 파일내용을 확인할 수 있다.
In [8]:
cat test.txt
다시 한 번 ls 명령어를 이용하여 test.txt 파일이 생성되었음을 확인할 수 있다.
In [9]:
ls
터미널 명령어가 아닌 파이썬 명령어를 이용하여 파일 내용을 확인하고자 한다면 다시 열어야 한다.
이번에는 내용을 추가하기 위해 'a' 모드로 열어본다.
In [10]:
f = open('test.txt', 'a')
'third line' 이란 문자열을 새 줄에 추가한다.
In [11]:
f.write("\nthird line")
In [12]:
f.close()
새 줄이 추가되었음을 확인할 수 있다.
In [13]:
cat test.txt
파일 내용을 읽기 위해서는 먼저 파일을 열어야 한다. 기본적으로 읽기전용 모드는 'r' 모드를 사용한다.
In [14]:
f = open('test.txt', 'r')
In [15]:
a = f.readlines()
In [16]:
a
Out[16]:
그런데 readlines 메소드를 다시 실행하면 빈 리스트를 리턴한다.
In [17]:
b = f.readlines()
b
Out[17]:
이유는 오프셋(offset)이라는 책갈피 역할을 하는 기능때문이다.
0으로 초기화된다.readlines 메소드를 한 번 실행하면 오프셋은 파일에 저장된 내용에 해당하는 바이트 값을 갖는다. text.txt 파일에 저장된 문자열은 총 33개이다. 따라서 readlines를 한 번 실행한 현재 오프셋의 값은 33이다.readlines를 한 번 이상 실행하면 아무 것도 읽지 못한다는 사실만 기억하면 된다.파일을 다시 처음부터 읽고 싶다면 우선은 열린 파일을 닫고 다시 열면 된다. 오프셋을 이용한 방식이 있기는 하지만 여기서는 다루지 않는다.
In [18]:
f.close()
f = open('test.txt', 'r')
In [19]:
a1 = f.readlines()
a1
Out[19]:
In [20]:
f.close()
In [21]:
f = open('test.txt', 'r')
a2 = f.read()
a2
Out[21]:
readlines 경우와 마찬가지로 read를 한 번 실행하면 오프셋이 파일의 끝을 가리킨다. 따라서 read를 한 번 실행하면 아무것도 읽지 못한다.
In [22]:
a3 = f.read()
a3
Out[22]:
In [23]:
f.close()
read 메소드는 readlines 메소드와 사실상 동일한 기능을 수행한다. 문자열 관련 메소드인 split을 사용하기만 하면 된다.
split(str)은 기존 문자열을 str을 기준으로 쪼개어 리스트로 리턴하는 기능을 수행한다.
인자를 넣지 않으면 줄바꾸기('\n') 또는 스페이스(' ')을 기본값으로 해서 줄바꾸기 또는 스페이스를 기준으로 쪼개어 리스트로 리턴한다.
In [24]:
c = a2.split('\n')
c
Out[24]:
In [25]:
f = open('test.txt', 'r')
b1 = f.readline()
b1
Out[25]:
readline을 반복적으로 실행할 때마다 다음 줄이 읽힌다. 오프셋이 줄 단위로 이동하기 때문이다.
In [26]:
b2 = f.readline()
b2
Out[26]:
In [27]:
b3 = f.readline()
b3
Out[27]:
오프셋이 파일 끝에 도달하면 더 이상 읽을 내용이 없어 빈 문자열을 리턴한다.
In [28]:
b4 = f.readline()
b4
Out[28]:
파일을 더이상 다루지 않는다면 항상 닫도록 한다.
In [29]:
f.close()
저장된 파일 내용을 확인한 후 원하는 자료만 추출하는 기본적인 방법을 배운다.
예제: 아래처럼 스페이스로 구분된 숫자들로 구성된 문자열이 있다고 가정하자.
"1 2.0 14 3.3 5"
어떻게 하면 스페이스로 구분된 숫자들의 합을 계산할 수 있을까? 즉,
1 + 2.0 + 14 + 3.3 + 5 = ?
우선 해당 문자열을 스페이스를 기준으로 쪼개는 split함수를 활용해야 한다. 이후에는 순수하게 숫자들오 구성된 문자열을 숫자 자료형(int 또는 float)로 형변환해야 한다.
int() 함수와 float() 함수를 활용하면 된다.
In [30]:
num_str = '1 2.0 14 3.3 5'
list_num_str = num_str.split()
sum = 0
for num in list_num_str:
sum = sum + float(num)
print("The total sum is {}!".format(sum))
먼저 장보기 목록 메모장을 만들어 보자. 새로운 장보기 목록임으로 파일을 새롭게 연다.
In [31]:
f = open('shopping_list', 'w')
장보기 목록을 입력한다.
In [32]:
f.write("bread 1 1.39\ntomatoes 6 0.26\nmilk 3 1.45")
더 이상 구입할 목록이 없으면 메모장을 닫는다.
In [33]:
f.close()
내용을 확인하면 다음과 같다.
In [34]:
cat shopping_list
이제 장을 볼 목록을 확인하기 위해 파일을 다시 연다.
readlines 메소드 이용하기
In [35]:
f = open('shopping_list', 'r')
buy_list = f.readlines()
f.close()
buy_list
Out[35]:
readline 메소드 이용하기: 단순하지 않지만 어렵지는 않다. 아래 코드를 이해하도록 노력해보자.
In [36]:
f = open('shopping_list', 'r')
buy_list = []
while True:
line = f.readline()
if line != '':
buy_list.append(line)
else:
break
f.close()
buy_list
Out[36]:
read 메소드 이용하기
In [37]:
f = open('shopping_list', 'r')
buy_list = f.read().split('\n')
f.close()
buy_list
Out[37]:
세 가지 방식 중에서 어떤 것도 사용할 수 있지만 지금 경우에 있어서는 read 메소드를 통해 좀 더 깔끔한 값을 얻었다.
이제 각 품목에 대해 필요한 경비를 계산할 수 있다. split으로 각 항목을 쪼갠 후 인덱싱을 이용하기만 하면 된다.
In [38]:
int(buy_list[0].split()[1]) * float(buy_list[0].split()[2])
Out[38]:
In [39]:
int(buy_list[1].split()[1]) * float(buy_list[1].split()[2])
Out[39]:
In [40]:
int(buy_list[2].split()[1]) * float(buy_list[2].split()[2])
Out[40]:
빵값, 토마토, 우유 비용을 계산하는 코드를 자세히 살펴보면 buy_list 인덱싱에 사용되는 인덱스 값만 0, 1, 2 순으로 변한 것을 알 수 있다. 따라서 총비용 계산은 for 문을 이용하면 된다.
In [41]:
sum = 0
for item in buy_list:
d = item.split()
item_price = int(d[1]) * float(d[2])
print("The price of {} is ${}.".format(d[0], item_price))
sum = sum + item_price
print("The total expense is ${}.".format(sum))
따라서 total_expense 함수를 아래와 같이 코딩할 수 있다.
In [42]:
def total_expense(memo):
f = open(memo,'r')
a = f.readlines()
sum = 0
for item in a:
d = item.split()
item_price = int(d[1]) * float(d[2])
print("The price of {} is ${}.".format(d[0], item_price))
sum = sum + item_price
print("The total expense is ${}.".format(sum))
이제 오늘 장을 보기 위해 필요한 총비용을 쉽게 확인할 수 있다.
In [43]:
total_expense('shopping_list')