파이썬(python) – 파일(File) 다루기

프로그래밍에서 가장 많이 사용하는 것 중의 하나가 파일을 다루는 방법이죠.
기본적으로 python 은 c 에서 파일 다루는 법과 거의 같다고 보시면 되겠습니다.

아래와 같이 text 파일을 하나 만들어둡니다.

sh> cat test.txt
a alpha
o omega
g gamma

test.txt 파일을 다루기 위한 프로그램인 hello.py 파일을 아래와 같이 만듭니다.
file 을 열 때는 open 이라는 내장함수를 사용합니다. help(open)을 보시면 open 함수의 리턴형은 file object 입니다.

import sys

def Cat(filename):
    f = open(filename, 'rU')
    # 메모리를 많이 사용하지 않는다. 일정 메모리만 잡고 반복적으로 읽을 뿐
for line in f:            
        print line
    # file 사용한 후에는 file fd 해제
f.close()

def main():
    # 첫번째 argument 를 Cat 함수에 넘김
    Cat(sys.argv[1])

if __name__ == '__main__':
    main()

실행해보니 new line 이 붙은 채로 한 줄씩 잘 찍어주네요 ^^

sh. python hello.py ./test.txt
a alpha       # new line 을 붙임

o omega

g gamma

그런데, 왜 new line 이 들어가서 한줄씩 더 들어가 있을까요?
file object 를 line by line 으로 찍어보면 끝에 new line 이 자동으로 붙습니다.
이는 사실 보이지는 않지만 test.txt 파일의 각 라인 끝에 new line 이 붙어있기 때문입니다. new line 도 하나의 character 로 취급이 되잖아요 ?
그러니까, print 에서 자동으로 붙여주는 new line 과 file object 를 구성하는 line 의 끝에 붙은 new line 이 합쳐져서 중간에 한줄이 더 들어간 것처럼 사이가 벌어진 것입니다.

어떤 함수의 리턴형이 궁금하면 dir 을 이용하거나 아래와 같이 python interpreter 상에서 프로그램 코드짜듯이 수행하여 직접 찍어보면 됩니다.

>>> import sys
>>> f = open("test.txt", 'r')
>>> for line in f: print line
...
a alpha

o omega

g gamma

# line 은 new line 이 붙은 sting
>>> line
'g gamman'              

python interpreter 를 실행한 후 다음과 같이 file 을 열어보세요.
open 의 결과로 리턴되는 file object 의 dir 을 보면 file object 에서 수행할 수 있는 함수 리스트를 볼 수 있네요.

>>> import sys
>>> f = open('test.txt','r')
>>> dir(f)

['__class__', '__delattr__', '__doc__', '__enter__', '__exit__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'closed', 'encoding', 'errors', 'fileno', 'flush', 'isatty', 'mode', 'name', 'newlines', 'next', 'read', 'readinto', 'readline', 'readlines', 'seek', 'softspace', 'tell', 'truncate', 'write', 'writelines', 'xreadlines']

c 나 c++ 에서처럼 file 을 다룰 때 사용할 수 있는 함수들이 거의 모두 들어가 있네요. ^^
각 함수의 argument 와 리턴형은 help(function_name)으로 확인하면 되겠죠.
python 은 객체를 이용하기 때문에 이렇게 객체에서 사용가능한 함수리스트를 쉽게 확인 가능한 것이 아주 큰 장점인 것 같습니다.
c 나 c++ 을 이용하여 unix 환경에서 프로그램을 개발하다 보면 함수 이름이 생각안날 때가 종종 있어서 불편할 때도 많죠. 함수 이름이 생각안나면 man page 를 볼 수도 없으니 그런 점이 불편하더군요. ㅎㅎ

이번에는 file 을 읽어서 각 라인의 값들을 list 로 묶어서 리턴해주는 readlines() 함수를 사용해서 실행해볼까요 ?

import sys

def Cat(filename):
    f = open(filename, 'rU')
    # lines 에 파일의 내용을 list 로 모두 담아준다. 메모리 사용량 주의 !!!
    lines = f.readlines()    
    print lines
    f.close()

def main():
    Cat(sys.argv[1])

if __name__ == '__main__':
    main()

아래의 결과를 보세요. 대괄호를 사용해서 list 로 리턴되었음을 확인할 수 있습니다.

sh> python hello.py ./test.txt
['a alphan', 'o omegan', 'g gamman']

갑자기 뜬금없는 이야기이지만, 참고로 python 에서는 변수에 어떤 이름을 붙일 것인가에 대한 naming 규칙이 다른 언어보다 10 배는 중요합니다. 특별히 어떤 변수 타입 선언을 별도로 하는 것이 아니고, 실행 중에 line by line 으로 파악하고 실행하는 interpreter 이기 때문에 만약 변수 이름을 모호하게 지어놓으면 프로그램의 가독성이 많이 떨어집니다.

자, 이번에는 file 을 읽어서 어떤 변환을 하지 말고 그냥 통 문자열로 리턴해달라고 할 수도 있겠죠.
그 때 이용하는 함수가 file object 의 read 함수입니다.

import sys

def Cat(filename):
    f = open(filename, 'rU')
    # 파일을 읽어서 full string 으로 돌려준다
    text = f.read()              
    print text
    f.close()

def main():
    Cat(sys.argv[1])

if __name__ == '__main__':
    main()

아래의 결과를 보시면 그냥 file 내용 그대로인 것을 확인할 수 있습니다.

sh> python hello.py ./test.txt
a alpha
o omega
g gamma

file 을 다 사용한 다음에는 되도록 위의 코드 처럼 f.close() 를 호출해주도록 하세요.
프로그램이 종료할 때라면 자동으로 시스템의 fd 자원을 반납하게 되지만, 프로세스가 기동된 상황에서 file close 를 해주지 않게 되면 fd 자원이 누수되어 언젠가는 바닥이 났다는 에러를 뜬금없이 만날 수도 있으니까요.

지금까지 file 다루는 법을 좀 살펴보았습니다.
사실 위의 내용 정도만 알고 있고 file 에 대한 개념만 알고 있으면 이보다 훨씬 고급기능도 어렵지 않게 사용할 수 있습니다.

You may also like...

0 0 votes
Article Rating
Subscribe
Notify of
guest
4 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Hub

초보자도 알기 쉽게 이해하도록 유용한 강의 올려주셔서 감사합니다.
특히 예제를 많이 실어주셔서 따라해 보기도 하고 한 눈에 들어와서 더욱 공부하기 좋았어요.
앞으로도 열심히 공부하겠습니다. ^^

구름과비21

와우… 칭찬 감사합니다.
앞으로 더욱 열심히 올려야겠군요 ^^

Hub

초보자도 알기 쉽게 이해하도록 유용한 강의 올려주셔서 감사합니다.
특히 예제를 많이 실어주셔서 따라해 보기도 하고 한 눈에 들어와서 더욱 공부하기 좋았어요.
앞으로도 열심히 공부하겠습니다. ^^

구름과ጆ

와우… 칭찬 감사합니다.
앞으로 더욱 열심히 올려야겠군요 ^^

4
0
Would love your thoughts, please comment.x
()
x