#!/usr/bin/env python # coding: utf-8 # *** # *** # # 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()) # 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)) # - close()을 마지막에 호출하지 않으면 해당 file 객체가 다른 값으로 치환되거나 프로그램이 종료될 때 자동으로 close()가 불리워진다. # - 하지만 명시적으로 close()를 호출하는 것을 권장함 # - with ~ as ~ 사용 추천 # - with ~ as ~ 블럭이 끝나면 자동으로 close()를 해줌 # In[1]: 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[2]: with open('t.txt', 'r') as f: s = f.read() print(s) print(type(s)) # ### 1-4 라인 단위로 파일 읽기 # - 총 4가지 방법 존재 # - 파일 객체의 반복자(iterator) 이용하기 # - 파일 객체의 반복자는 각 라인별로 내용을 읽어오도록 설정되어 있음 # - 파일을 라인별로 읽는 방법 중 가장 효과적임 # - readline(): 한번에 한줄씩 읽는다. # - readlines(): 파일 전체를 라인 단위로 끊어서 리스트에 저장한다. # - xreadlines(): python3.6에서는 지원하지 않음 # - 파일 객체의 반복자 사용 # In[3]: f = open('t.txt') i = 1 for line in f: print(i, ":", line, end="") i += 1 f.close() # - readline() 사용 # In[4]: 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() # - readlines() 사용 # - 각 라인을 모두 읽어서 메모리에 리스트로 저장함 # - 대용량 파일인 경우 사용 비추천 # In[5]: 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() # In[6]: 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() # - 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() # ### 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() # - 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() # - 텍스트 파일 t.txt의 단어(공백으로 분리된 문자열) 수를 출력하는 방법 # In[8]: f = open('t.txt') s = f.read() print(s) n = len(s.split()) print(n) f.close() # ### 1-6 기존 파일에 내용 추가 # In[12]: f = open('removeme.txt', 'w') # 파일의 생성 f.write('first line\n') f.write('second line\n') f.close() # In[13]: f = open('removeme.txt', 'a') # 파일 추가 모드로 오픈 f.write('third line\n') f.close() f = open('removeme.txt') # 파일 읽기 print(f.read()) f.close() # ### 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() # *** # ## 2 표준 출력 방향 전환 # *** # # - sys 모듈의 표준 입출력 관련 객체 # - sys.stdout: 표준 출력 # - sys.stderr: 표준 에러 출력 # - sys.stdin: 표준 입력 # - 예를 들어, sys.stdout을 파일 객체로 변환하면 모든 표준 출력(print 출력)은 해당 파일로 저장된다. # ### 2-1 표준 출력을 파일로 저장하기 # In[14]: 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[15]: f = open('t.txt') print(f.read()) # In[16]: print("Hello koreatech!", file=open("output.txt", "w")) # In[17]: f = open('output.txt') print(f.read()) # - print를 직접 이용하여 출력을 다른 객체로 전환하기 # - 아래와 같은 방식은 python3에서 더이상 지원하지 않음 # In[22]: print >> sys.stderr, "Warning, action field not supplied" # - 대신 아래 방법 사용 # In[23]: print("Warning, action field not supplied", file=sys.stderr) # - 동일 방법으로 표준 출력(print)을 파일 객체로 전환 # In[24]: f = open('t.txt', 'w') print('spam string', file=f) f.close() f = open('t.txt') print(f.read()) f.close() # ### 2-2 StringIO 모듈 사용하기 # - StringIO 모듈의 StringIO 클래스 객체 # - 파일 객체처럼 입출력 가능한 문자열 객체 # - StringIO에 지원되는 메소드는 파일 객체가 지원하는 메소드와 거의 동일하다. # - getvalue() 메소드 # - 현재까지 담아 놓은 전체 내용을 반환한다. # In[18]: import StringIO f = StringIO.StringIO() f.write("abc") f.seek(0) s = f.read() print(s) print() s2 = f.getvalue() print(s2) # - 표준 출력으로 문자열 객체에 내용 작성하기 # - python3 에서는 io 모듈내에 StringIO 클래스 존재 # In[22]: import sys from io import StringIO f = StringIO() f.write("abc") f.write("def") q = f.read() print(q) q1 = f.getvalue() print(q1) f.close() # In[43]: def f1(): s = "" for i in range(10000, 1000000): s += str(i) def f2(): s = StringIO() for i in range(10000, 1000000): s.write(str(i)) # In[44]: get_ipython().run_line_magic('timeit', 'f1()') # In[45]: get_ipython().run_line_magic('timeit', 'f2()') # In[19]: 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) # *** # ## 3 파일로의 지속 모듈 # *** # - 지속성(Persistence) # - 프로그램 내에 생성된 각종 객체들을 해당 프로그램 종료 이후에도 존재하게 만들고, 그것들을 동일한 또는 다른 프로그램에서 사용하는 기능 # - 지속성 기능을 지원하는 모듈 # - DBM 관련 모듈 # - anydbm, dbm, gdbm, dbhash, dumbdbm # - anydbm: 시스템에서 사용가능한 모듈 중 가장 최적의 모듈을 반환함 # - 기본적으로 dumbdbm을 반환한다 # - 사전 자료형을 사용하는 것과 동일한 방법으로 사용 # - **pickle** 모듈 # - 파이썬의 객체를 저장하는 일반화된 지속성 모듈 # - 파이썬의 기본 객체뿐만 아니라 사용자 정의의 복잡한 객체도 저장 가능 # - 기본적으로 텍스트 모드로 저장하지만 이진 모드로도 저장 가능 # - 피클링(pickling) 모듈 사용하기 # - file을 open 할 때 이진 파일로 open 하기 # - 즉, 모드로서 'wb', 'rb' 적용 # In[47]: import pickle phone = {'tom':4358382, 'jack':9465215, 'jim':6851325, 'Joseph':6584321} List = ['string', 1234, 0.2345] Tuple = (phone, List) # 리스트, 튜플, 사전의 복합 객체 with open('pickle.txt', 'wb') as f: # 파일 객체를 얻는다. pickle.dump(Tuple, f) # 파일로 출력(pickling), 복합 객체 출력 with open('pickle.txt', 'rb') as f: x,y = pickle.load(f) # 파일에서 읽어오기. 튜플의 내용을 x, y에 받는다. print(x) # 사전 print(y) # 리스트 # In[49]: import pickle class Simple: # 가장 단순한 클래스를 정의 pass s = Simple() # 인스턴스 객체 생성 s.count = 10 # 인스턴스 이름 공간에 변수 생성 with open('pickle2.txt', 'wb') as f: pickle.dump(s, f) # 인스턴스 저장 with open('pickle2.txt', 'rb') as f: t = pickle.load(f) # 인스턴스 가져오기 print(t.count) # #### [참고] 다양한 파일 처리 모드 # # - open 내장 함수의 두번째 인자 mode 설명 # - 두번째 인자 mode 생략시에는 읽기 전용(r) 모드로 설정 # # | Mode | 간단 설명 | 자세한 설명 # |--------|-----------------------------|------------| # | 'r' | 읽기 전용(기본 모드) | 파일 객체를 읽기 모드로 생성하고, 파일 포인터를 파일 처음 위치에 놓는다.| # | 'w' | 쓰기 전용(기존 파일 내용 삭제) | 파일이 존재하지 않으면 새로운 파일을 쓰기 모드로 생성하고, 해당 파일이 이미 존재하면 내용을 모두 없에면서 쓰기 모드로 생성하고, 파일 포인터를 파일 처음 위치에 놓는다. | # | 'a' | 파일 끝에 추가(쓰기 전용) | 파일이 존재하지 않으면 새롭게 파일을 생성하면서 쓰기 모드로 생성하고, 해당 파일이 이미 존재하면 파일 객체을 쓰기 모드로 생성하면서 파일 포인터를 파일의 마지막 위치에 놓는다. 따라서, 이후 작성되는 내용은 파일의 뒷 부분에 추가됨.| # | 'r+' | 읽고 쓰기 | 파일 객체를 읽고 쓸 수 있도록 생성한다. 파일 포인터를 파일 처음 위치에 놓는다. | # | 'w+' | 읽고 쓰기(기존 파일 내용 삭제) | 파일 객체를 읽고 쓸 수 있도록 생성한다. 파일이 존재하지 않으면 새로운 파일을 생성하고, 해당 파일이 이미 존재하면 내용을 모두 없에면서 생성하고, 파일 포인터를 파일 처음 위치에 놓는다.| # | 'a+' | 읽고 쓰기(파일 끝에 추가) | 파일 객체를 읽고 쓸 수 있도록 생성한다. 파일이 존재하지 않으면 새롭게 파일을 생성하고, 해당 파일이 이미 존재하면 파일 객체을 생성하면서 파일 포인터를 파일의 마지막 위치에 놓는다 (그래서, 이후 작성되는 내용은 파일의 뒷 부분에 추가). | # # # - 이진 파일로 저장을 위해서는 아래 모드 사용 # # | Mode | 간단 설명 | # |--------|-----------------------------| # | 'rb' | 이진 파일 읽기 전용 | # | 'wb' | 이진 파일 쓰기 전용(기존 파일 내용 삭제) | # | 'ab' | 이진 파일 끝에 추가(쓰기 전용) | # | 'rb+' | 이진 파일 읽고 쓰기 | # | 'wb+' | 이진 파일 읽고 쓰기(기존 파일 내용 삭제) | # | 'ab+' | 이진 파일 끝에 추가(읽기도 가능) | # # # #

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