파일 입·출력


 지금까지 공부하면서 짰던 코드들은 프로그램이 종료되면 그대로 종료됩니다. 출력하는 내용이나 코드를 파일로 저장하고 읽어오면 다시 사용할 수 있겠죠? 파일 입·력은 파일을 열어서 쓰고 덧붙이는 방법으로, 다른 프로그래밍 언어와 유사한 형태로 사용합니다. 

- open() 내장 함수


 파일 입출력은 open()이라는 내장함수를 이용하고, 사용이 끝나면 close() 함수로 종료를 해줘야 합니다. close() 쓰지않아도 자동으로 자원을 반납하지만, 코드의 가독성을 위해서라도 써주는게 좋다고합니다. 

 아래 내용은 open() 내장 함수의 세부적인 내용입니다.
----------------------------------------------------------------------------------------

- open("filename",'mode')


- open()함수의 모드

1. 'r'(read) : 생략을 하면 기본적으로 사용되는 모드로, 읽기 전용모드, 파일 포인터를 처음위치에 놓음

2. 'w'(write) : 쓰기모드로 존재하지 않는 파일은 생성하고, 존재하는 파일내용을 모두 지우고 파일포인터를 처음위치에 놓음

3. 'a'(append) : 이미 존재하는 파일 뒤쪽에 내용을 추가, 파일 포인터를 파일의 마지막 위치에 놓음


- 이진 파일로 저장하기 위한 모드

1. rb

2. wb

3. ab

----------------------------------------------------------------------------------------


- 파일 쓰기


 파일을 쓰기에 앞서 현재 작업중인 디렉토리를 알아보는 명령을 알아보겠습니다. os모듈을 임포트하고 getcwd() 함수를 이용하면 현재 작업중인 디렉토리를 확인할 수 있습니다. 파일 쓰게되면 같은 경로에 파일이 생기게됩니다.

----------------------------------------------------------------------------------------

import os

print os.getcwd() # 현재 작업중인 디렉토리를 알아보는 함수

----------------------------------------------------------------------------------------
(실행 결과)

D:\PythonProject\Python\13

----------------------------------------------------------------------------------------


 open() 내장 함수를 이용해 파일 쓰기를 해 보겠습니다. 파일에 쓰기위해서는 write()메소드를 활용 합니다.
----------------------------------------------------------------------------------------
s='''애써 미안한 표정 하지마
싫어진 거잖아 이제 널 떠나줄게
비겁해지는 널 보는 게 아파
내가 갈게 널 보내줄게
-권진아 끝 中에서- '''

f=open('end.txt','w') # 'end.txt' 쓰기모드로 열기
f.write(s) # s 문자열을 파일에 써줌
f.close() # 자원 반납
----------------------------------------------------------------------------------------
 위 코드를 실행하면, 이클립스 콘솔창에는 아무런 내용이 출력되지 않습니다. 작업중인 코드의 경로에 가면 텍스트 파일이 하나 생성되어 있습니다. 


- 파일 읽기


이번에는 이클립스에서 텍스트 파일을 읽어보겠습니다. 파일을 읽을때에는 read()메소드를 이용합니다.

----------------------------------------------------------------------------------------
f=open('end.txt') # 모드 생략 시 읽기 모드
s2=f.read()
print s2
----------------------------------------------------------------------------------------
(실행 결과)
애써 미안한 표정 하지마
싫어진 거잖아 이제 널 떠나줄게
비겁해지는 널 보는 게 아파
내가 갈게 널 보내줄게
-권진아 끝 中에서- 
----------------------------------------------------------------------------------------


- 라인단위로 파일 읽기/쓰기


 파일을 읽을때 라인단위로 읽을 수가 있습니다. 라인 단위로 읽는 방법은 총 4가지가 있습니다.


1. 객체 반복자 사용

 아래와 같이 for-in 문을 이용해서 라인 단위로 출력이 가능합니다. 파일을 라인단위로 읽을때 가장 효율적인 방법이라고 합니다.

----------------------------------------------------------------------------------------
f=open('end.txt')

i=1

for line in f:

    print i,":",line,

    i+=1

f.close()

----------------------------------------------------------------------------------------
(실행 결과)
1 : 애써 미안한 표정 하지마
2 : 싫어진 거잖아 이제 널 떠나줄게
3 : 비겁해지는 널 보는 게 아파
4 : 내가 갈게 널 보내줄게
5 : -권진아 끝 中에서- 
----------------------------------------------------------------------------------------

2. readline() 사용
 readline()을 사용할때에는 while문을 이용합니다. 현재의 파일포인터에서 개행문자까지 읽어줍니다. 아래코드에서는 줄바꿈을 개행문자로 인지합니다. 실행 결과는 위와 동일합니다.
----------------------------------------------------------------------------------------
f=open('end.txt')
line=f.readline()
i=1
while line:
    print i,":",line,
    line=f.readline() # 파일 포인터가 개행문자 다음의 가장 처음에 위치합니다.
    i+=1
f.close()
----------------------------------------------------------------------------------------


3. readlines() 사용

 각 라인을 모두 읽어서 메모리에 리스트 형태로 저장합니다. 라인이 100줄 1000줄이면 메모리를 굉장히 비효율적으로 사용하게 됩니다. 한글이여서 아스키코드로 변화해서 저장되는걸 확인 할 수 있습니다.

----------------------------------------------------------------------------------------
f=open('end.txt')

print f.readlines() # 리스트로 저장

print # 한줄 개행


f.seek(0) # 파일포인터를 처음으로 되돌려줌

i=1


for line in f:

    print i,":",line,

    i+=1

f.close()

----------------------------------------------------------------------------------------
(실행 결과)
['\xec\x95\xa0\xec\x8d\xa8 \xeb\xaf\xb8\xec\x95\x88\xed\x95\x9c \xed\x91\x9c\xec\xa0\x95 \xed\x95\x98\xec\xa7\x80\xeb\xa7\x88\n', '\xec\x8b\xab\xec\x96\xb4\xec\xa7\x84 \xea\xb1\xb0\xec\x9e\x96\xec\x95\x84 \xec\x9d\xb4\xec\xa0\x9c \xeb\x84\x90 \xeb\x96\xa0\xeb\x82\x98\xec\xa4\x84\xea\xb2\x8c\n', '\xeb\xb9\x84\xea\xb2\x81\xed\x95\xb4\xec\xa7\x80\xeb\x8a\x94 \xeb\x84\x90 \xeb\xb3\xb4\xeb\x8a\x94 \xea\xb2\x8c \xec\x95\x84\xed\x8c\x8c\n', '\xeb\x82\xb4\xea\xb0\x80 \xea\xb0\x88\xea\xb2\x8c \xeb\x84\x90 \xeb\xb3\xb4\xeb\x82\xb4\xec\xa4\x84\xea\xb2\x8c\n', '-\xea\xb6\x8c\xec\xa7\x84\xec\x95\x84 \xeb\x81\x9d \xe4\xb8\xad\xec\x97\x90\xec\x84\x9c- ']

1 : 애써 미안한 표정 하지마
2 : 싫어진 거잖아 이제 널 떠나줄게
3 : 비겁해지는 널 보는 게 아파
4 : 내가 갈게 널 보내줄게
5 : -권진아 끝 中에서- 
----------------------------------------------------------------------------------------

4. xreadlines() 사용

 위의 readlines()의 메모리 비효율성을 개선할 수 있는 함수입니다. 리스트가 반환되지 않고, 파일 객체 내용이 찍힙니다. 사용과 실행 결과는 위와 동일합니다.



 그렇다면, 반대로 라인단위로 파일 쓰는건 어떻게 할까요? 이미 위에서 사용했던 write() 함수와 wrtielines() 함수가 있습니다. 라인단위로 파일을 쓸때에는개행문자(\n)를 꼭 써줘야 합니다.

----------------------------------------------------------------------------------------

f=open("end.txt",'a') # 기존 파일에 내용 추가

f.writelines('\n\n')

f.writelines('오늘은 2월 22일 \n')

f.writelines('하루종일 날씨가 흐리다.\n')

f.writelines('얼른 봄이 왔으면 좋겠다.\n')

f.close()


f=open('end.txt')

print f.read()

----------------------------------------------------------------------------------------

(실행 결과)

애써 미안한 표정 하지마

싫어진 거잖아 이제 널 떠나줄게

비겁해지는 널 보는 게 아파

내가 갈게 널 보내줄게

-권진아 끝 中에서- 


오늘은 2월 22일 

하루종일 날씨가 흐리다.

얼른 봄이 왔으면 좋겠다.

----------------------------------------------------------------------------------------


- 파일 내 임의 위치로 접근


 위에서 몇번 언급한 파일포인터는 파일 내에서 현재 위치를 가리키고 있습니다. 이때 seek(5)를 하면 문자열의 5번째 인덱스를 가리키게 됩니다.

 tell()을 사용하면 현재 위치를 돌려주고, read(1)을 사용하게되면 현재 위치에서 문자하나를 읽고나서 파일포인터를 하나 이동합니다.


- 표준 출력 방향 전환


 일반적으로 print 함수를 사용하게되면 문자열을 화면(콘솔)에 출력하게됩니다. sys 모듈의 sys.stdout의 표준출력이 정해져있기 때문인데, 이를 바꿔주면 print함수를 사용하면 바꿔준 형태로 실행이 됩니다.

 아래 코드는 표준출력을 파일에 저장하는것으로 바꾸고 실행 후 다시 되돌리는 코드입니다.

----------------------------------------------------------------------------------------

# -*- coding: utf-8 -*-


import sys

f=open('t.txt','w')

stdout=sys.stdout # 표준출력 저장(백업 개념)

sys.stdout=f


print '테스트 메시지1'

print '테스트 메시지2'

print '테스트 메시지3'


f.close()

sys.stdout=stdout # 다시 원상태로 되돌려줌

----------------------------------------------------------------------------------------

 아래와같이 화면(콘솔)에 출력되는것이 아니라 't.txt'파일에 문자열이 써집니다.


 이밖에도 sys모듈에는 sys.stderr(표준 에러출력)과 sys.stdin(표준 입력)이 있습니다. stderr을 변경하면, 에러메시지 처럼 콘솔창에 빨간색 글씨로 출력이 됩니다.


- StringIO 모듈 사용

 StringIO 모듈의 StringIO 클래스 객체는 사용하면, 파일 객체처럼 입출력 가능한  문자열 객체로, StringIO에 지원되는 메소드는 파일 객체가 지원하는 메소드와 거의 유사합니다. 메소드중에서 getvalue() 메소드가 있는데 현재까지 담아 놓은 전체 내용을 반환하는 메소드입니다.

----------------------------------------------------------------------------------------

import StringIO


f=StringIO.StringIO()

f.write('abc')

f.seek(0)

s=f.read()

print s


f.write('def')

s2=f.getvalue()

print s2

----------------------------------------------------------------------------------------

(실행 결과)

abc

abcdef

----------------------------------------------------------------------------------------


- 파일로의 지속 모듈


- 지속성 : 프로그램 내에 생성된 각종 객체들을 해당 프로그램 종료이후에도 존재하게 만들고, 그것들을 동일한 또는 다른 프로그램에서 사용하는 기능

- 지속성 기능을 지원하는 모듈

DBM 관련 모듈 : anydbm, dbm, gdbm, dbhash, dumbdbm

pickling 모듈 : 파이썬의 객체를 저장하는 일반화된 지속성 모듈


 pickling 모듈이 좀 더 일반적으로 사용한다고해서 pickle모듈만 사용해 봤습니다. 이클립스에서는 에러가 발생해서 Enthought Canopy로 실습을 진행했습니다.

----------------------------------------------------------------------------------------

import pickle


color={'r':'red','g':'green','b':'blue'}

fruits=['banana','apple','grape']

Tuple=(color,fruits)


f=open('pickle.txt','w')


pickle.dump(Tuple,f) # 저장하고자 하는 Tuple을 f에 넣어서 얼림

f.close()


####################################


f=open('pickle.txt')


x,y=pickle.load(f) # dump()와 반대

print x

print y

----------------------------------------------------------------------------------------




출처 한국기술교육대학교 온라인평생교육원 파이썬프로그래밍




'언어 > Python' 카테고리의 다른 글

[파이썬] 디렉토리 다루기  (0) 2017.02.25
[파이썬] 파일 다루기  (0) 2017.02.24
[파이썬] 사전  (0) 2017.02.19
[파이썬] 튜플과 집합자료형  (0) 2017.02.14
[파이썬] 리스트 활용  (4) 2017.02.07

+ Recent posts