본문 바로가기

파일 다루기 | 파일 입출력

파이썬에서 파일을 다룰 때는 'open()' 함수로 파일을 열고 'close()'로 닫습니다. 모드는 'r'(읽기), 'w'(쓰기), 'a'(추가)가 있으며, 'with'문을 사용하면 자동으로 파일이 닫힙니다.

1. python에서 파일 다루기

파이썬에서는 파일과 폴더를 다룰 수 있습니다. 이번 시간에는 파이썬으로 파일을 읽고, 쓰고, 추가하는 것을 알아보도록 하겠습니다. 파일을 읽고 쓰고 추가하는 것 모두 close를 해주셔야 합니다. 먼저 간단하게 colab에서 실행해 보도록 하겠습니다.

# open(파일이름, 파일모드)
f = open('python.txt', 'w') # 파일모드 : r, w, a, r+,
f.close()

실행해보면 colab 화면 좌측에 python.txt라고 텍스트 파일이 생성된 것을 볼 수 있습니다.

파이썬의 파일을 생성할 때 open( )이라는 내장함수를 사용합니다. 이 때 생성할 파일의 이름과 파일 모드를(읽기, 쓰기, 추가하기) 같이 입력해 주어야 합니다.

2. 모드에 관하여

f = open('python.txt', 'w') # r, w, a, r+, w+, a+
f.close()

파일 객체는 f = open('파일이름', '모드')와 같은 형태로 파일에 대한 객체를 얻을 수 있습니다.

  • 'r': 읽기 모드. 파일을 읽기만 할 때 사용합니다. 파일이 존재하지 않으면 오류가 발생합니다.
  • 'w': 쓰기 모드. 파일에 쓸 때 사용합니다. 파일이 이미 존재하면 내용을 지우고 새로 쓰기 시작합니다. 파일이 존재하지 않으면 새로운 파일을 생성합니다.
  • 'a': 추가 모드. 파일의 마지막에 새로운 내용을 추가할 때 사용합니다. 파일이 존재하지 않으면 새로운 파일을 생성합니다.
  • 'r+': 읽기와 쓰기 모드. 파일을 열 때 기존의 내용을 보존합니다. 파일을 열 때 포인터가 가장 앞에 있습니다.
  • 'w+': 읽기와 쓰기 모드. 파일을 열 때 기존의 내용을 삭제합니다. 다만 열어서 쓴 내용은 읽을 수 있습니다.
  • 'a+': 읽기와 추가 모드. 파일을 열 때 포인터가 가장 뒤에 가 있습니다.

3. 파일 쓰기

방금 생성된 'python.txt' 파일을 더블 클릭하여 보면 빈 파일이라는 사실을 알 수 있습니다. 내용을 넣지 않고 생성만 했기 때문인데요. 이번에는 파일을 쓰는(write) 방법에 대해 알아보겠습니다.

f = open('student.txt', 'w')
l = ['licat', 'mura', 'binky']
s = ''
for i, j in enumerate(l, 1):
    s += f'{i}번 {j}입니다.\n'
f.write(s)
f.close()

문자열 끝에 \n을 붙인 것에 주목해주세요. 이것이 없으면 세 사람의 정보가 모두 한 줄에 이어 붙습니다. 파일에서 '줄'을 나누는 것은 오직 개행 문자뿐입니다.

다시 파일을 더블 클릭하여 열어보면 좀 전에는 없던 내용이 새로 생성이 되어 있는 것을 볼 수 있습니다.

아래와 같이 다른 양식에 파일을 생성하는 것도 가능합니다.

f = open('index.html', 'w')
s = '''<html>
<head>
</head>
<body>
<h1>hello world</h1>
</body>
</html>
'''
f.write(s)
f.close()
# 쉬운예제
f = open('student.csv', 'w')
s = '''학년,반,번,이름
1,3,1,licat
1,3,2,mura
1,3,3,binky
'''
f.write(s)
f.close()

csv파일 같은 경우 다운 받아 엑셀에서도 열어볼 수 있으며, colab에서는 아래와 같이 시각화 하여 보여줍니다.

4. 파일 읽기

파일을 읽는 방법에는 4가지가 있습니다.

4.1 readline()

readline 메서드를 이용하여 방금 생성한 파일을 일어보도록 하겠습니다.

f = open('student.txt', 'r')
while True:
    line = f.readline()
    if not line:
        break
    print(line)
f.close()

아래 출력 결과에서 개행이 2번씩 되는 이유는 print에 end가 \n이기 때문에 그렇습니다. print(line, end='')이면 개행을 한 번씩 하게 됩니다.

4.2 readlines()

readline은 파일의 텍스트 한 줄을 읽어오지만, readlines는 전체 라인을 읽어옵니다. 출력 결과는 위와 동일합니다.

f = open('student.txt', 'r')
lines = f.readlines()
for line in lines:
    print(line)
f.close()

4.3 read()

read 함수를 사용하면 파일의 전체 내용을 읽어올 수 있습니다.

f = open('student.txt', 'r')
data = f.read()
print(data)
f.close()

4.4 파일 객체를 직접 순회하기

실무에서 가장 많이 쓰는 방법입니다. 파일 객체 자체가 순회 가능한 객체라서 for문에 바로 넣을 수 있습니다. 한 줄씩 꺼내 쓰기 때문에 파일이 아무리 커도 메모리를 적게 사용합니다.

with open('student.txt', 'r', encoding='utf-8') as f:
    for line in f:
        print(line, end='')

readlines()는 파일 전체를 리스트로 만들어 메모리에 올리지만, 위 방식은 필요한 줄만 그때그때 읽어옵니다. 대용량 로그 파일을 다룰 때 이 차이가 크게 벌어집니다.

5. 내용 수정

다음은 이미 생성된 파일에 내용을 수정하는 방법입니다.

f = open('student.txt', 'a')
s = 'hello world!'
f.write(s)
f.close()

실행시킨 후 파일을 다시 열어보시면 아래와 같이 파일에 텍스트가 추가된 것을 볼 수 있습니다.

6. 파일 열기와 닫기를 동시에

위에서 파일을 생성하고 그 파일에 텍스트를 쓰는 방법에 대해 배웠습니다. with문을 사용하면 블록을 벗어나는 순간 파일이 자동으로 닫힙니다. 중간에 에러가 나더라도 반드시 닫아주기 때문에, 실무에서는 close()를 직접 호출하는 대신 with문을 사용합니다.

with open('test.txt', 'w') as f:
    f.write('hello world!')

생성된 test.txt 파일로 들어가면 텍스트가 포함되어 있는 것을 알 수 있습니다.

7. 나아가기

+ 모드에 대해 살펴보도록 하겠습니다.

7.1 r+ 모드

r+모드는 읽기와 쓰기를 동시에 하는 모드입니다. 파일을 읽을 때 처음부터 읽어나가며, 쓰기를 하면 덮어쓰게 됩니다. 파일이 없으면 에러가 나기 때문에 아래처럼 파일 생성 후 테스트해보도록 하겠습니다.

with open('test.txt', 'w') as f:
    f.write('hello world')
f = open('test.txt', 'r+')
print(f.read())
f.write('\nr+모드입니다!\n')
print('-----')
f.seek(0)  # 파일의 시작 위치로 이동, 주석처리 해보세요.
print(f.read())
f.close()

위 모드에서 f.seek(0)는 포인터를 맨 앞으로 이동시키는 코드입니다. 포인터는 커서라고 생각하시면 됩니다. 이렇게 하지 않으면 뒤로가있는 포인터부터 읽게 됩니다.

hello world  # print(f.read())
-----        # print('-----')
hello world  # print(f.read())
r+모드입니다! # 이어 작동

주석처리를 요청한 곳에 코드를 실행시키겠습니다. 비교를 위해 2개의 코드를 동시 실행합니다.

with open('test.txt', 'w') as f:
    f.write('hello world')

f = open('test.txt', 'r+')
# f.seek(0)
print(f.read())
f.write('\nr+모드입니다!\n')
print('-----')
# f.seek(0) # 파일의 시작 위치로 이동, 주석처리 해보세요.
print(f.read())
f.close()
hello world  # print(f.read())
-----        # print('-----')

f.seek이 주석처리되면서 읽을 때 커서가 맨 끝에 가 있는 상태에서 읽었기 때문에 아무것도 읽지 못하게 됩니다.

7.2 w+ 모드

w+ 모드는 읽고 쓰는 모드입니다. 여기는 쓰기가 우선이기에 파일을 열 때 기존에 있던 내용을 지우고, 새로 작성합니다. 여기서 읽기가 가능한 것은 기존에 있는 내용을 읽을 수 있다는 얘기가 아니라 지금 쓴 내용은 읽기가 가능하다는 얘기입니다.

with open('test.txt', 'w') as f:
    f.write('hello world')

f = open('test.txt', 'w+')
f.seek(0) # 커서를 앞으로 보냈음에도 기존에 텍스트를 읽지 못합니다. 이미 지워졌기 때문입니다.
print(f.read())
f.write('w+모드입니다!')
f.seek(0) # 쓴 내용을 읽을 수는 있습니다.
print(f.read()) # 출력: w+모드입니다!
f.close()

이처럼 r+ 모드는 파일을 열 때 기존의 내용을 보존하고 w+ 모드는 파일을 열 때 기존의 내용을 삭제한다는 차이가 있습니다.

7.3 a+ 모드

r+모드와 다르게 포인터를 앞으로 주지 않으면 내용을 읽지 못합니다. 추가하는 모드이기에 포인터가 맨 끝으로 가있기 때문입니다. write를 하더라도 기존 내용에 추가된 것을 확인할 수 있습니다.

with open('test.txt', 'w') as f:
    f.write('hello world')

f = open('test.txt', 'a+')
f.seek(0)
print(f.read())
f.write('\na+모드입니다!')
print('-----')
f.seek(0)
print(f.read())
f.close()
# 출력
hello world
-----
hello world # 기존 내용이 보존되어 있습니다.
a+모드입니다!