파이썬 기초 강좌 #18 파일 읽기, 쓰기 – 2편 (file read, write – vol.2)

12 분 소요

이번 강좌에서는 지난강좌에 이어서 파일 쓰기에 대해서 공부하도록 하겠습니다. 만약에 지난 강좌를 보지 않았다면, 아래의 링크를 통해서 먼저 파일 읽기에 대해서 공부하시기 바랍니다.

파이썬 기초 강좌 #17 파일 읽기, 쓰기 – 1편 (file read, write – vol.1)

파일 읽기, 쓰기 모드

모드설명
r읽기 전용 모드이며 디폴트 옵션이기 때문에 생략을 하셔도 됩니다.
w쓰기 전용 모드이며, 같은 이름의 파일이 없으면 새로운 파일을 생성하고, 있으면 덮어쓰기를 합니다. 덮어쓰기를 하면 기존 파일의 데이터가 모드 지워지니 주의하시기 바랍니다.
x쓰기 전용 모드이지만, 같은 이름의 파일이 존재하면 에러를 발생시킵니다. w 모드의 안전모드라고 생각하시면 됩니다.
a추가 모드이며, 같은 이름의 파일이 없으면 새로운 파일을 생성하고, 있으면 하단에서 부터 이어쓰기를 하는 모드입니다.
t텍스트 모드로 디폴트 모드이니 생략이 가능합니다.
b바이너리 모드로 PDF나 이미지 파일등과 같이 일반 텍스트 파일이 아닌 바이너리로 만들어진 파일을 열 때 사용하는 모드입니다.
r+읽기와 쓰기를 동시에 할 수 있는 모드입니다.
w+읽기와 쓰기를 동시에 할 수 있는 모드입니다.

파일을 쓰는 방법은 파일을 읽는 방법과 상당히 비슷합니다. 파일을 읽을 때와 마찬가지로 open 함수를 사용하며 모두 파라미터에 w, x, a 옵션 중에서 하나를 사용하시면 됩니다

먼저 w 옵션을 사용해서 파일 쓰기를 해보겠습니다. 쓰기를 하기 위해서는 file 오브젝트가 가지고 있는 write 메소드를 사용하시면 됩니다. write 메소드는 문자열을 인수로 받아서 파일에 쓰는 역할을 합니다.

파이썬 코드
with open(file='out.txt', mode='w', encoding='utf8') as file:
    file.write('line one')
    file.write('line two')
out.txt
line oneline two

두 줄을 쓰려고 했는데 한 줄에 입력되는 문제가 발생했습니다. write 메소드는 줄바꿈을 하지 않기 때문에 이런 문제가 발생하는 것입니다. 아래 코드와 같이 뉴라인(\n) 캐릭터를 넣어주시면 문제가 해결 됩니다.

파이썬 코드
with open(file='out.txt', mode='w', encoding='utf8') as file:
    file.write('line one\n')
    file.write('line two\n')
out.txt
line one
line two

두 줄로 잘 출력되었습니다. 매번 뉴라인 캐릭터를 넣는 게 귀찮다고 하시는 분들은 아래 코드와 같이 print 함수를 사용하시면 됩니다. help 함수를 사용해서 print 함수에 대한 도움말을 확인해 보겠습니다.

파이썬 쉘
help(print)
콘솔 출력
Help on built-in function print in module builtins:
 
print(...)
    print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
    
    Prints the values to a stream, or to sys.stdout by default.
    Optional keyword arguments:
    file:  a file-like object (stream); defaults to the current sys.stdout.
    sep:   string inserted between values, default a space.
    end:   string appended after the last value, default a newline.
    flush: whether to forcibly flush the stream.

프린트 함수는 end 파라미터에 디폴트 값으로 뉴라인 캐릭터를 가지고 있고 file 파라미터에 sys.stdout 값을 디폴트로 가지고 있습니다. sys.stdout 이란 커맨드창이나 터미널이라고 생각하시면 됩니다. 이 file 파라미터에 인수로 file 오브젝트를 전달하고 실행하면 문자열이 콘솔에 출력되지 않고 파일에 쓰여지며 매번 문자열 끝에 뉴라인 캐릭터를 추가하지 않아도 됩니다.

파이썬 코드
with open(file='out.txt', mode='w', encoding='utf8') as file:
    print('line 1', file=file)
    print('line 2', file=file)
out.txt
line 1
line 2

코드를 다시 실행할 때마다 파일에 저장되어 있던 텍스트는 다 지워지고 새로운 텍스트가 입력되는 것을 볼 수 있는데요, w 모드를 사용할 경우 "out.txt"라는 이름의 파일이 없으면 새로운 파일을 생성하고, 이미 존재하는 경우에는 새로운 텍스트로 덮어쓰기를 하기 때문에 기존의 텍스트는 모두 지워진다는 점 꼭 기억하시고 잘못해서 데이터를 다 날려버리는 일이 없도록 주의하시기 바랍니다.

이번에는 국가정보가 들어가 있는 딕셔너리의 값을 파일에 써보도록 하겠습니다.

파이썬 코드
countries = [
    {'국가명': '대한민국', '수도명': '서울', '지역명': '아시아'},
    {'국가명': '일본', '수도명': '토쿄', '지역명': '아시아'},
    {'국가명': '중국', '수도명': '베이징', '지역명': '아시아'},
]
 
with open(file='country.txt', mode='w', encoding='utf8') as file:
    for country in countries:
        line = '국가명: {국가명}, 수도명: {수도명}, 지역명: {지역명}\n'.format(**country)
        file.write(line)
country.txt
국가명: 대한민국, 수도명: 서울, 지역명: 아시아
국가명: 일본, 수도명: 토쿄, 지역명: 아시아
국가명: 중국, 수도명: 베이징, 지역명: 아시아

데이터가 파일에 잘 저장된 것을 확인하였습니다. 이렇게 프로그램에서 정의한 리스트나 딕셔너리를 텍스트 파일에 저장하려면 str 함수를 사용하시면 됩니다.

파이썬 코드
countries = [
    {'국가명': '대한민국', '수도명': '서울', '지역명': '아시아'},
    {'국가명': '일본', '수도명': '토쿄', '지역명': '아시아'},
    {'국가명': '중국', '수도명': '베이징', '지역명': '아시아'},
]
 
with open(file='country.txt', mode='w', encoding='utf8') as file:
    file.write(str(countries))
country.txt
[{'국가명': '대한민국', '수도명': '서울', '지역명': '아시아'}, {'국가명': '일본', '수도명': '토쿄', '지역명': '아시아'}, {'국가명': '중국', '수도명': '베이징', '지역명': '아시아'}]

파일에 리스트 오브젝트가 코드와 같은 형식으로 저장되었습니다. 이렇게 저장된 오브젝트를 다시 읽어 들이면 파이썬 인터프리터는 이것을 리스트 오브젝트로 인식하지 못하고 문자열로 리턴합니다. 확인해 보겠습니다.

파이썬 코드
countries = [
    {'국가명': '대한민국', '수도명': '서울', '지역명': '아시아'},
    {'국가명': '일본', '수도명': '토쿄', '지역명': '아시아'},
    {'국가명': '중국', '수도명': '베이징', '지역명': '아시아'},
]
 
with open(file='country.txt', mode='r', encoding='utf8') as file:
    result = file.read()
    print(type(result))
콘솔 출력
<class 'str'>

파일에 저장된 데이터를 프로그램에서 읽어들여 다시 사용하고 싶을 때는 아래 코드와 같이 eval 함수를 사용하여 리스트나 딕셔너리 오브젝트로 변환하여 사용하실 수가 있습니다.

파이썬 코드
countries = [
    {'국가명': '대한민국', '수도명': '서울', '지역명': '아시아'},
    {'국가명': '일본', '수도명': '토쿄', '지역명': '아시아'},
    {'국가명': '중국', '수도명': '베이징', '지역명': '아시아'},
]
 
with open(file='country.txt', mode='r', encoding='utf8') as file:
    result = file.read()
    result = eval(result)
    print(type(result))
콘솔 출력
<class 'list'>

리스트 오브젝트로 변한 되었으니 위에 정의한 딕셔너리 에 리스트 처럼 똑같이 사용하실수가 있습니다.

파이썬 코드
countries = [
    {'국가명': '대한민국', '수도명': '서울', '지역명': '아시아'},
    {'국가명': '일본', '수도명': '토쿄', '지역명': '아시아'},
    {'국가명': '중국', '수도명': '베이징', '지역명': '아시아'},
]
 
with open(file='country.txt', mode='r', encoding='utf8') as file:
    result = file.read()
    result = eval(result)
    for country in result:
        print(country)
콘솔 출력
{'국가명': '대한민국', '수도명': '서울', '지역명': '아시아'}
{'국가명': '일본', '수도명': '토쿄', '지역명': '아시아'}
{'국가명': '중국', '수도명': '베이징', '지역명': '아시아'}

이번에는 mode 파라미터의 x 옵션에 대해서 알아보겠습니다. 앞에서 x 옵션은 w 모드의 안전 모드와 같다고 설명을 드렸는데요, 이 옵션을 사용하면 같은 이름의 파일이 있으면 에러를 발생시켜주기 때문에 실수로 데이터를 날려버리는 문제를 방지할 수가 있습니다.

파이썬 코드
with open(file='country.txt', mode='x', encoding='utf8') as file:
    file.write('새로운 데이터')
콘솔 출력
---------------------------------------------------------------------------
FileExistsError                           Traceback (most recent call last)
<ipython-input-9-e897f33b1472> in <module>
----> 1 with open(file='country.txt', mode='x', encoding='utf8') as file:
      2     file.write('새로운 데이터')
 
FileExistsError: [Errno 17] File exists: 'country.txt'

FileExistsError 에러가 발생하면서 프로그램이 종료된 것을 볼 수 있습니다.

이번에는 mode 파라미터의 a 옵션에 대해서 알아보겠습니다 a 옵션은 추가 모드로써 같은 이름의 파일이 없으면 새로운 파일을 생성하고, 같은 이름의 파일이 있으면 w 옵션과 같이 덮어쓰기를 하는 것이 아니고, 파일이 열리면서 커서가 파일 가장 끝에 위치하게 되고, 커서가 있는 부분부터 이어쓰기를 하게 됩니다.

append.txt
기존 데이터

한 줄의 텍스트가 들어있는 append.txt 파일에 a 옵션을 사용해서 파일에 텍스트를 추가해보겠습니다.

파이썬 코드
with open(file='append.txt', mode='a', encoding='utf8') as file:
    file.write('추가한 텍스트')
append.txt
기존 데이터추가한 텍스트

추가한 텍스트가 기존 데이터와 같은 줄의 입력되어 버렸는데요, 파일에 텍스트를 추가할 때는 기존 텍스트의 마지막 줄이 줄바꿈이 있는지를 확인하시고 없다면, 다음과 같이 추가할 텍스트의 앞부분에 뉴 라인 캐릭터를 추가 하시기 바랍니다.

파이썬 코드
with open(file='append.txt', mode='a', encoding='utf8') as file:
    file.write('\n추가한 텍스트')
append.txt
기존 데이터
추가한 텍스트

일반 텍스트 읽기 쓰기에 대한 공부는 여기서 마치고 CSV, JSON, YAML, EXCEL 등과 같은 특수 포맷의 파일을 다루는 방법은 별도의 강좌에서 다루도록 하겠습니다.

다음 강좌에서는 에러와 예외 처리에 대해서 공부하도록 하겠습니다. 수고하셨습니다~! 😉