특정 파일을 열어 저장된 데이터를 읽거나 특정 데이터를 특정 파일에 저장해야 하는 일이 매우 빈번하게 발생한다.
예를 들어 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')