[파이썬3.0]데이터 저장과 예외처리-finally,with절 등

프로그램 언어/파이썬|2014. 6. 23. 20:59
데이터 저장




데이터를 파일에서 불러와서 사용한 뒤에 혹은, 새로 생성한 데이터를 보관하는 방법을 알아보자.

데이터를 보관해야 나중에 사용할 수도 있기에 저장은 중요하다.
또한 데이터는 저장하기도 하지만 화면에도 출력해야 하고 네트워크를 통해 다른 이에게 전송해야 할 때도 있다.



코드
man = []
other = []

try:
    data = open('sketch.txt')

    for each_line in data:
        try:
            (role, line_spoken) = each_line.split(':', 1)
            line_spoken = line_spoken.strip()#공백 문자 제거
            if role == 'Man':
                man.append(line_spoken)
            elif role == 'Other Man':
                other.append(line_spoken)
        except ValueError:
            pass

    data.close()
except IOError:
    print('The datafile is missing!')

print(man)
print(other)



출력

['Is this the right room for an argument?', "No you haven't!", 'When?', "No you didn't!", "You didn't!", 'You did not!', 'Ah! (taking out his wallet and paying) Just the five minutes.', 'You most certainly did not!', "Oh no you didn't!", "Oh no you didn't!", "Oh look, this isn't an argument!", "No it isn't!", "It's just contradiction!", 'It IS!', 'You just contradicted me!', 'You DID!', 'You did just then!', '(exasperated) Oh, this is futile!!', 'Yes it is!']
["I've told you once.", 'Yes I have.', 'Just now.', 'Yes I did!', "I'm telling you, I did!", "Oh I'm sorry, is this a five minute argument, or the full half hour?", 'Just the five minutes. Thank you.', 'Anyway, I did.', "Now let's get one thing quite clear: I most definitely told you!", 'Oh yes I did!', 'Oh yes I did!', 'Yes it is!', "No it isn't!", 'It is NOT!', "No I didn't!", 'No no no!', 'Nonsense!', "No it isn't!"]


필요한 부분을 나눠 각각의 리스트로 저장을 한 뒤에 그 리스트들을 출력했다.
각각의 리스트가 제대로 출력이 되었다.

그러나 지금까지 코드는 읽어오는 용도로 사용한 코드이다.
그럼 지금 리스트에 저장된 데이터를 다른 파일에 쓰는 작업을 해보자.

part 파일에 데이터 입력

파일에 입력을 할 때도 open()함수를 사용한다.
방법은 아래와 같다.

객체 = open("파일명", "w")

이렇게 하면 해당 파일을 열긴 열되 'w' 쓰기모드(write)로 연다.
이렇게 해야 파일에 데이터를 저장할 수 있다.

print('파일에 쓸 내용', file=객체명)

위에 print()함수를 사용해서 저장할 수 있다.

작업을 다 끝낸 후에는 반드시 파일을 닫아야 한다.
그래야 캐시에 남아있던 데이터도 실제 파일에 써진다고 한다.
이것을 플러싱(flushing)이라고 하며, 매우 중요하고...

객체명.close()


연습
코드
man = []
other = []

try:
    data = open('sketch.txt')

    for each_line in data:
        try:
            (role, line_spoken) = each_line.split(':', 1)
            line_spoken = line_spoken.strip()
            if role == 'Man':
                man.append(line_spoken)
            elif role == 'Other Man':
                other.append(line_spoken)
        except ValueError:
            pass

    data.close()
except IOError:
    print('파일이 없다구!!!')

try:
    man_file = open('man.txt', 'w')
    other_file = open('other.txt', 'w')

    print(man, file=man_file)
    print(other, file=other_file)

    man_file.close()
    other_file.close()
except IOError:
    print('파일이 이상한데?')

위에 코드를 실행하면 man.txt와 other.txt 파일이 생성된다.
그것을 열어보면 위에 리스트를 출력했을 때 보여준 값들이 들어 있다.

에러발생시

여기서 만약 에러가 print()함수로 내려 쓰는 중 발생한다면?

파일에 데이터를 쓴 때에는 읽을 때의 IOError발생 보다 큰 문제가 발생된다.
그 이유는
try:
    man_file = open('man.txt', 'w')
    other_file = open('other.txt', 'w')

    print(man, file=man_file)
    print(other, file=other_file)#여기서 문제가 발생!!!!

    man_file.close()# 여기서부터
    other_file.close()#여기까진 실행이 안된다.
except IOError:
    print('파일이 이상한데?')

위와 같이 중간에 에러가 발생하면 내려 쓰던 중 파일을 닫지 않고 바로 에러처리 부분으로 넘어간 뒤에 
프로그램이 종료된다.


반드시 작동해야 할 예외 처리

finally:

방금 전과 같이 다른 문제가 발생하더라도 꼭 처리해야 할 예외 처리를 하는 방법이 있다.
바로 finally: 이다.

finally스위트는 무슨 일이 있더라도 동작을 합니다.

try:
     man_file = open('man.txt', 'w')
     other_file = open('other.txt', 'w')

     print(man, file=man_file)
     print(other, file=other_file)

except IOError:
     print('파일이 이상한데?')

finally:
     man_file.close()
     other_file.close()
    
그냥 위에 작성한 것에서 변한 것은 close()부분을 finally 스위트 안에 이동한 것 뿐이다.
이러면 무조건 플러싱은 하기에 데이터 저장을 해준다.
 
try - WITH문

위에 finally 스위트로 처리하는 방법이 있는 것을 보았다.

locals() 내장 함수로 파일이름이 있는지 확인하고, 있으면 close()매서드를 호출하여 닫게 하여 에러를 막을 수 있다.
그러나 위에 처리 방식에서 추가로 에러코드를 확인 하려면 as를 이용하면 에러 메세지도 상세히 출력할 수 있다.
escept: IOError as err:
     print('File error: ' + str(err))#str()내장함수를 이용해야 문자열로 변환해서 출력할 수 있다. 안 그러면 에러 발생.

위 과정을 하게 되면 finally 스위트에 대해 locals()함수를 사용해야 파일 존재 유무를 판단해서 없을 때 에러가 발생되지 않게 할 수 있다.
그러나 좀 복잡해진다.

그래서 다른 방법도 있다.
with문을 이용하는 것이다.

코드

man = []
other = []

try:
    data = open('sketch.txt')

    for each_line in data:
        try:
            (role, line_spoken) = each_line.split(':')
            line_spoken = line_spoken.strip()
            if role == 'Man':
                man.append(line_spoken)
            elif role == 'Other Man':
                other.append(line_spoken)
            else:
                pass
        except ValueError:
            pass

    data.close()
except IOError:
    print('파일이 없다구!!!')

try:
    with open('man_data.txt', 'w') as man_file, open('other_data.txt', 'w') as other_file:
        print(man, file=man_file)
        print(other, file=other_file)
except IOError as err:
    print('File error: ' + str(err))


위와 같이 처리하면 아주 코드가 간단해진다. 
with문은 해당 파일이 있는지 없는지 검사도 해주고 열려있는 파일을 자동으로 닫아준다.

파이썬 인터프리터가 자동으로 처리해주기에 아주 편하다.
콘텍스트 관리 프로토콜이라는 파이썬 기술을 사용한다.


참고 : headfirst python, 파이썬3 바이블


'프로그램 언어 > 파이썬' 카테고리의 다른 글

[파이썬3.0] 데이터 정렬  (0) 2014.06.24
[파이썬3.0] 객체에 대해  (0) 2014.06.24
[파이썬3.0] 피클링  (0) 2014.06.15
[파이썬3.0] 모듈 공유  (0) 2014.06.15
[파이썬3.0] 예외처리(에러처리)  (1) 2014.06.11

댓글()