13. 파일 입출력



  • 파일을 열어서 읽고, 쓰고, 덧붙이는 방법
    • open(filename, mode) 내장 함수로 filename 이름을 지닌 file 객체를 얻는다.
    • 얻어진 파일 객체에서 자료를 읽거나, 쓰거나, 덧붙이는 작업 수행
    • 모든 작업이 끝나면 close()를 호출하여 작업 프로세스의 자원 점유 해제

1 파일 입출력 방법


1-1 파일 처리 모드의 종류

  • open 내장 함수의 두번째 인자 mode 설명
    • 두번째 인자 mode 생략시에는 읽기 전용(r) 모드로 설정
Mode 간단 설명 자세한 설명
'r' 읽기 전용 (기본 모드) 파일 객체를 읽기 모드로 생성하고, 파일 포인터를 파일 처음 위치에 놓는다.
'w' 쓰기 전용 새로운 파일을 쓰기 모드로 생성하거나 해당 파일이 이미 존재하면 내용을 모두 없에면서 쓰기 모드로 생성하고, 파일 포인터를 파일 처음 위치에 놓는다.
'a' 파일 끝에 추가 이미 존재하는 파일을 쓰기 모드로 생성하거나 파일이 존재하지 않으면 새롭게 파일을 생성하면서 쓰기 모드로 생성하고, 파일 포인터를 파일의 마지막 위치에 놓는다. 그래서, 이후 작성되는 내용은 파일의 뒷 부분에 추가된다.
  • 이진 파일로 저장을 위해서는 아래 모드 사용
Mode 간단 설명
'rb' 이진 파일 읽기 전용
'wb' 이진 파일 쓰기 전용
'ab' 이진 파일 끝에 추가

1-2 파일 쓰기

In [1]:
import os

print(os.getcwd())
/Users/yhhan/git/python-e-learning/python3.6
In [2]:
s = """Its power: Python developers typically report 
they are able to develop applications in a half
to a tenth the amount of time it takes them to do
the same work in such languages as C."""
f = open('t.txt', 'w')
f.write(s) # 문자열을 파일에 기록
f.close()

1-3 파일 읽기

  • read() 메소드 사용
    • 대용량 파일인 경우 사용 비추천
In [3]:
#f = file('t.txt') 
f = open('t.txt', 'r')
s = f.read()
print(s)
print(type(s))
Its power: Python developers typically report 
they are able to develop applications in a half
to a tenth the amount of time it takes them to do
the same work in such languages as C.
<class 'str'>
  • close()을 마지막에 호출하지 않으면 해당 file 객체가 다른 값으로 치환되거나 프로그램이 종료될 때 자동으로 close()가 불리워진다.
    • 하지만 명시적으로 close()를 호출하는 것을 권장함
  • with ~ as ~ 사용 추천
    • with ~ as ~ 블럭이 끝나면 자동으로 close()를 해줌
In [4]:
s = """Its power: Python developers typically report 
they are able to develop applications in a half
to a tenth the amount of time it takes them to do
the same work in such languages as C."""
with open('t.txt', 'w') as f:
    f.write(s) # 문자열을 파일에 기록
In [5]:
with open('t.txt', 'r') as f:
    s = f.read()
    print(s)
    print(type(s))
Its power: Python developers typically report 
they are able to develop applications in a half
to a tenth the amount of time it takes them to do
the same work in such languages as C.
<class 'str'>

1-4 라인 단위로 파일 읽기

  • 총 4가지 방법 존재
    • 파일 객체의 반복자(iterator) 이용하기
      • 파일 객체의 반복자는 각 라인별로 내용을 읽어오도록 설정되어 있음
      • 파일을 라인별로 읽는 방법 중 가장 효과적임
    • readline(): 한번에 한줄씩 읽는다.
    • readlines(): 파일 전체를 라인 단위로 끊어서 리스트에 저장한다.
    • xreadlines(): python3.6에서는 지원하지 않음
  • 파일 객체의 반복자 사용
In [6]:
f = open('t.txt')
i = 1
for line in f:
    print(i, ":", line, end="")
    i += 1
f.close()
1 : Its power: Python developers typically report 
2 : they are able to develop applications in a half
3 : to a tenth the amount of time it takes them to do
4 : the same work in such languages as C.
  • readline() 사용
In [7]:
f = open('t.txt')
line = f.readline()
print(type(line))
i = 1
while line:
    print(i, ":", line, end="")
    line = f.readline()
    i += 1
f.close()
<class 'str'>
1 : Its power: Python developers typically report 
2 : they are able to develop applications in a half
3 : to a tenth the amount of time it takes them to do
4 : the same work in such languages as C.
  • readlines() 사용
    • 각 라인을 모두 읽어서 메모리에 리스트로 저장함
    • 대용량 파일인 경우 사용 비추천
In [9]:
f = open('t.txt')
print(f.readlines())
print(type(f.readlines()))
print()

f.seek(0)
i = 1
for line in f.readlines():
    print(i, ":", line, end="")
    i += 1
f.close()
['Its power: Python developers typically report \n', 'they are able to develop applications in a half\n', 'to a tenth the amount of time it takes them to do\n', 'the same work in such languages as C.']
<class 'list'>

1 : Its power: Python developers typically report 
2 : they are able to develop applications in a half
3 : to a tenth the amount of time it takes them to do
4 : the same work in such languages as C.
In [10]:
f = open('t.txt')
print(f.readlines())
print(type(f.readlines()))
print()
f.close()

f = open('t.txt')
i = 1
for line in f.readlines():
    print(i, ":", line, end="")
    i += 1
f.close()
['Its power: Python developers typically report \n', 'they are able to develop applications in a half\n', 'to a tenth the amount of time it takes them to do\n', 'the same work in such languages as C.']
<class 'list'>

1 : Its power: Python developers typically report 
2 : they are able to develop applications in a half
3 : to a tenth the amount of time it takes them to do
4 : the same work in such languages as C.
  • xreadlines() 사용 (python3에서는 지원하지 않는 메소드)
    • python3에서는 xreadlines()사용과 파일 객체 f의 반복자 사용하는 경우와 동일함.
In [11]:
f = open('t.txt')
print(f.xreadlines())
print()

f.seek(0)
i = 1
for line in f.xreadlines():
    print(i, ":", line,)
    i += 1
f.close()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-11-58fb3beae1a7> in <module>()
      1 f = open('t.txt')
----> 2 print(f.xreadlines())
      3 print()
      4 
      5 f.seek(0)

AttributeError: '_io.TextIOWrapper' object has no attribute 'xreadlines'

1-5 라인 단위로 파일 쓰기

  • writelines(): 리스트 안에 있는 각 문자열을 연속해서 파일로 출력한다.
In [12]:
lines = ['first line\n', 'second line\n', 'third line\n']
f = open('t1.txt', 'w')
f.writelines(lines)
f.close()

f = open('t1.txt')
print(f.read())
f.close()
first line
second line
third line

  • write() 이용하여 여러 문자열을 각 라인별로 파일로 출력하는 방법
In [13]:
lines = ['first line', 'second line', 'third line']
f = open('t1.txt', 'w')
f.write('\n'.join(lines))
f.close()

f = open('t1.txt')
print(f.read())
f.close()
first line
second line
third line
  • 텍스트 파일 t.txt의 단어(공백으로 분리된 문자열) 수를 출력하는 방법
In [14]:
f = open('t.txt')
s = f.read()
n = len(s.split())
print(n)
f.close()
35

1-6 기존 파일에 내용 추가

In [15]:
f = open('removeme.txt', 'w') # 파일의 생성
f.write('first line\n')
f.write('second line\n')
f.close()
In [16]:
f = open('removeme.txt', 'a') # 파일 추가 모드로 오픈
f.write('third line\n')
f.close()

f = open('removeme.txt')      # 파일 읽기
print(f.read())
first line
second line
third line

1-7 파일 내 임의 위치로 접근

  • 파일 포인터 (pointer)
    • 파일 내에서 현재 위치를 가리키고 있음
  • 파일 접근 방법
    • 순차 접근 (기본 방식): 파일을 앞에서 부터 순차적으로 읽고 쓰는 방식
    • 임의 접근: 파일 내 임의 위치에서 읽고 쓰는 방식
      • 임의 접근을 위한 file 객체 포인터 (pointer) 관련 메소드
        • seek(n): 파일의 가장 첫번째 위치에서 n번째 바이트로 포인터 이동
        • tell(): 파일 내 현재 포인터 위치를 반환
In [17]:
name = 't.txt' 
f = open(name, 'w+')   # 읽고 쓰기로 오픈, 단, 파일이 이미 존재한다면 기존 파일은 없어지고 다시 생성된다.
s = '0123456789abcdef'
f.write(s)

f.seek(5)       # 시작부터 5바이트 포인터 이동
print(f.tell())  # 현재 위치 돌려줌
print(f.read(1)) # 1문자 읽기
print(f.tell())
print()
5
5
6


2 표준 출력 방향 전환


  • sys 모듈의 표준 입출력 관련 객체
    • sys.stdout: 표준 출력
    • sys.stderr: 표준 에러 출력
    • sys.stdin: 표준 입력
  • 예를 들어, sys.stdout을 파일 객체로 변환하면 모든 표준 출력(print 출력)은 해당 파일로 저장된다.

2-1 표준 출력을 파일로 저장하기

In [18]:
import sys

f = open('t.txt', 'w')
stdout = sys.stdout   # 표준 출력 저장해 두기
sys.stdout = f        # 파일 객체로 표준 출력 변경
print('Sample output')
print('Good')
print('Good')
f.close()
sys.stdout = stdout   # 표준 출력 원상 복구
In [19]:
f = open('t.txt')
print(f.read())
Sample output
Good
Good

In [20]:
print("Hello koreatech!", file=open("output.txt", "w"))
In [21]:
f = open('output.txt')
print(f.read())
Hello koreatech!

  • print를 직접 이용하여 출력을 다른 객체로 전환하기
    • 아래와 같은 방식은 python3에서 더이상 지원하지 않음
In [22]:
print >> sys.stderr, "Warning, action field not supplied"
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-22-3654042ca1da> in <module>()
----> 1 print >> sys.stderr, "Warning, action field not supplied"

TypeError: unsupported operand type(s) for >>: 'builtin_function_or_method' and 'OutStream'. Did you mean "print(<message>, file=<output_stream>)"?
  • 대신 아래 방법 사용
In [23]:
print("Warning, action field not supplied", file=sys.stderr)
Warning, action field not supplied
  • 동일 방법으로 표준 출력(print)을 파일 객체로 전환
In [24]:
f = open('t.txt', 'w')
print('spam string', file=f)
f.close()

f = open('t.txt')
print(f.read())
f.close()
spam string

2-2 StringIO 모듈 사용하기

  • StringIO 모듈의 StringIO 클래스 객체
    • 파일 객체처럼 입출력 가능한 문자열 객체
    • StringIO에 지원되는 메소드는 파일 객체가 지원하는 메소드와 거의 동일하다.
    • getvalue() 메소드
      • 현재까지 담아 놓은 전체 내용을 반환한다.
In [25]:
import StringIO

f = StringIO.StringIO()
f.write("abc")
f.seek(0)
s = f.read()
print(s)
print()

s2 = f.getvalue()
print(s2)
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-25-1df50562a35a> in <module>()
----> 1 import StringIO
      2 
      3 f = StringIO.StringIO()
      4 f.write("abc")
      5 f.seek(0)

ModuleNotFoundError: No module named 'StringIO'
  • 표준 출력으로 문자열 객체에 내용 작성하기
    • python3 에서는 io 모듈내에 StringIO 클래스 존재
In [36]:
import sys
from io import StringIO

stdout = sys.stdout    # 표준 출력 저장해 두기
sys.stdout = f = StringIO()  

print(type(f))
print('Sample output')
print('Good')
print('Good')

sys.stdout = stdout
In [37]:
s = f.getvalue()

print('Done-------')
print(s)
Done-------
<class '_io.StringIO'>
Sample output
Good
Good


3 파일로의 지속 모듈


  • 지속성(Persistence)
    • 프로그램 내에 생성된 각종 객체들을 해당 프로그램 종료 이후에도 존재하게 만들고, 그것들을 동일한 또는 다른 프로그램에서 사용하는 기능
  • 지속성 기능을 지원하는 모듈
    • DBM 관련 모듈
      • anydbm, dbm, gdbm, dbhash, dumbdbm
      • anydbm: 시스템에서 사용가능한 모듈 중 가장 최적의 모듈을 반환함
        • 기본적으로 dumbdbm을 반환한다
        • 사전 자료형을 사용하는 것과 동일한 방법으로 사용
    • pickle 모듈
      • 파이썬의 객체를 저장하는 일반화된 지속성 모듈
      • 파이썬의 기본 객체뿐만 아니라 사용자 정의의 복잡한 객체도 저장 가능
      • 기본적으로 텍스트 모드로 저장하지만 이진 모드로도 저장 가능
  • 피클링(pickling) 모듈 사용하기
    • file을 open 할 때 이진 파일로 open 하기
      • 즉, 모드로서 'wb', 'rb' 적용
In [41]:
import pickle

phone = {'tom':4358382, 'jack':9465215, 'jim':6851325, 'Joseph':6584321}
List = ['string', 1234, 0.2345]
Tuple = (phone, List) # 리스트, 튜플, 사전의 복합 객체

f = open('pickle.txt', 'wb') # 파일 객체를 얻는다.

pickle.dump(Tuple, f) # 파일로 출력(pickling), 복합 객체 출력 
f.close() 

f = open('pickle.txt', 'rb')     
                      
x,y = pickle.load(f) # 파일에서 읽어오기. 튜플의 내용을 x, y에 받는다.
print(x) # 사전
print(y) # 리스트
{'tom': 4358382, 'jack': 9465215, 'jim': 6851325, 'Joseph': 6584321}
['string', 1234, 0.2345]
In [43]:
import pickle

class Simple: # 가장 단순한 클래스를 정의
    pass

s = Simple() # 인스턴스 객체 생성
s.count = 10 # 인스턴스 이름 공간에 변수 생성

f = open('pickle2.txt', 'wb')
pickle.dump(s, f) # 인스턴스 저장
f.close()

f = open('pickle2.txt', 'rb')
t = pickle.load(f) # 인스턴스 가져오기
print(t.count)
10

참고 문헌: 파이썬(열혈강의)(개정판 VER.2), 이강성, FreeLec, 2005년 8월 29일