[파이썬3.0] 예외처리(에러처리)

프로그램 언어/파이썬|2014. 6. 11. 21:51

예외처리(에러처리)

 

이번에는 전체를 part1과는 다르게 한 문장을 분할(쪼개서)해서 데이터를 가공해서 출력을 해보자.

 

파이썬 코드

import os

data = open('sketch.txt')

for each_line in data:

    (role, line_spoken) = each_line.split(':')

    print(role, end='')

    print(' said: ', end='')

    print(line_spoken,end='')

 

여기서 split()메서드는 각각의 라인을 잘라내는 것으로, 문자열의 리스트를 반환한다.

이 리스트가 대입 연산자 왼쪽의 타깃 식별자에 대입된다.

":"을 기점으로 양 옆을 쪼개는 거라고 보면 된다.

예를 들면, 위에서는 role에는 MAN이라는 문자열이 대입, line_spoken에는 대사가 들어간다.

위에 for문이기 때문에 각각 라인에 대해서 해당 역할과 대사가 나뉘어 저장되어 출력되는 것을 의미한다.

 

출력 결과

Other Man said: Oh I'm sorry, is this a five minute argument, or the full half hour?

Man said: Ah! (taking out his wallet and paying) Just the five minutes.

Other Man said: Just the five minutes. Thank you.

Other Man said: Anyway, I did.

Man said: You most certainly did not!

Traceback (most recent call last):

File "C:/Python33/ex_read.py", line 12, in <module>

(role, line_spoken) = each_line.split(':')

ValueError: too many values to unpack (expected 2)

 

위에서 잘 될 것처럼 되더니 문제가 발생이 되어 중간에 멈췄다.

왜 멈췄을까?

텍스트파일을 열어 확인해보면,

Man: You most certainly did not!

Other Man: Now let's get one thing quite clear: I most definitely told you!

":" 이 한 번이 아닌 두 번 존재하기 때문에 문제가 발생한 것을 볼 수 있다.

Split(':')은 ':' 이것을 기점으로 나누게 된다고 언급했는데, 여기서 ':'이 두 번 나오기 때문에 3등분을 하게 된 것이다. 그러나 우린 각각 나눈 조각을 2개만 받게 설정했으니 마지막 조각을 받는 것이 없기 때문에 에러가 발생된 것이다.

에러설명을 보면 위에 내용을 알 수 있다.

ValueError: too many values to unpack (expected 2)

값이 오류인데, 값이 많다고 알려준다. 그리고 괄호 안에 2개가 기대된다고 나온다.

즉 2개 값만 가능한데 그 이상이 나온 것이라는 것을 보여준 것이다.

 

>>> help(each_line.split)#help()는 설명을 보여준다. 여기서는 each_line.split()에 대한 설명을 출력.

Help on built-in function split:

 

split(...)

S.split(sep=None, maxsplit=-1) -> list of strings

 

Return a list of the words in S, using sep as the delimiter string.

If maxsplit is given, at most maxsplit splits are done. If sep is not specified

or is None, any whitespace string is a separator and empty strings are

removed from the result.

 

여기서 split()메서드는 나누는 기준이 되는 것을 최대 몇 번 일지 정할 수 있다.

기본적으로는 최대한 다 나눈다.

Maxsplit을 1로 주면 위에 에러는 발생하지 않게 된다.

왜냐하면 1번만 나누라는 의미가 되기에 뒤에 만나는 ':'는 처리하지 않기 때문이다.

 

그럼 수정해 보자.

 

파이썬 코드

import os

data = open('sketch.txt')

 

for each_line in data:

    (role, line_spoken) = each_line.split(':',1)

    print(role, end='')

    print(' said: ', end='')

    print(line_spoken,end='')

 

출력 결과

Man said: You most certainly did not!

Other Man said: Now let's get one thing quite clear: I most definitely told you!

Man said: Oh no you didn't!

Other Man said: Oh yes I did!

Man said: Oh no you didn't!

Other Man said: Oh yes I did!

Man said: Oh look, this isn't an argument!

Traceback (most recent call last):

File "C:/Python33/ex_read2.py", line 5, in <module>

(role, line_spoken) = each_line.split(':',1)

ValueError: need more than 1 value to unpack

 

위에 보면 에러가 처리되어 넘어간 것을 볼 수 있다.

그러나 다시 문제가 발생 되었다. 왜지???

 

텍스트파일을 보면 (pause) 라는 것이 있다. 바로 이것이 에러를 발생시킨 원인이다.

왜냐하면 한 줄에 ':'이 없을 경우이기 때문에 찾지 못하여 에러가 발생되었다.

에러설명을 보면,

ValueError: need more than 1 value to unpack

1개의 값보단 많아야 한다는 의미가 바로 ':'이 하나는 존재해야 한다는 의미이다.

 

Find()메서드를 이용하면 위에 에러를 해결할 수 있다.

이 메서드는 ()안에 값을 찾는 메서드이고 찾으면 해당하는 양의 인덱스 값을 반환한다.

그러나 찾지 못하면, -1을 반환한다.

 

파이썬 코드

import os

data = open('sketch.txt')

 

for each_line in data:

if not each_line.find(':') == -1: #not은 조건의 반대를 의미. 

                                      #즉, 찾았다면 이라는 의미가 됨.

        (role, line_spoken) = each_line.split(':',1)

        print(role, end='')

        print(' said: ', end='')

    print(line_spoken,end='')

 

data.close()

 

출력 결과

Other Man said: Now let's get one thing quite clear: I most definitely told you!

Man said: Oh no you didn't!

Other Man said: Oh yes I did!

Man said: Oh no you didn't!

Other Man said: Oh yes I did!

Man said: Oh look, this isn't an argument!

Other Man said: Yes it is!

 

에러가 발생하지 않았다. 이제 에러를 다 잡았다.

하지만 위와 달리 처리할 수도 있다.

 

Try:/except:

 

파이썬 코드

import os

data = open('sketch.txt')

 

for each_line in data:

    try:

        (role, line_spoken) = each_line.split(':',1)

        print(role, end='')

        print(' said: ', end='')

        print(line_spoken,end='')

    except:

        pass

 

data.close()

 

try:/except: 를 사용하는 방법이다.

이것은 예외처리 기법이다.

과정은

Try: 안에 있는 구문을 수행할 때 에러가 발생하는지를 조사하고 그 구문을 수행하다 에러가 발생되면 except: 안에 있는 것을 수행함으로써 예외적인 것들 처리한다.

 

이렇게 하면 위에 if처럼 조건을 생각하는 것을 안 해도 된다. 

그렇기 때문에 try:/except: 를 사용하는 것이 더 좋을 때가 있다. 

코드도 좀 더 심플해지기 때문이다.

 

 

위에 두 코드 모두 잘 수행되었다. 그러나 뭔가 없다.

그건 바로!! (pause)가 없다!!!

괄호가 나온 줄은 그냥 지나가게 만든 코드라서 그렇다.

Pass대신 print(each_line, end='')를 하면 괄호가 나온 줄도 출력이 된다.

 

 

파이썬 코드

try:

    data = open('sketch.txt')

 

    for each_line in data:

try:

            (role, line_spoken) = each_line.split(':', 1)

            print(role, end='')

            print(' said ', end='')

            print(line_spoken, end='')

except:

            pass

 

    data.close()

except:

    print(' 파일이 없는 데?')

색깔을 다르게 표시한 것은 그 색깔이 있는 범위는 같은 색깔의 except가 처리하기 때문이다.

(빨깡try안에 구문은 빨강except안에 있는 것을 우선 처리)

 

위와 같이 처리하는 방식은 올바르지 않을 수 있다.

왜냐하면 처리하는 에러 범위가 너무 광범위하기 때문이다.

다른 것으로 발생한 에러도 try안에 있다면 except에 있는 처리 방식을 따르기 때문에

오히려 이것으로 더 큰 문제가 발생될 수도 있다.

 

이것을 방지 하기 위해서는 except: 가 아닌 except xxxxx: 로 설정하면 된다.

즉, 특정한 에러명을 지정함으로써 해당하는 에러를 처리하게 만드는 것이다.

 

파이썬 코드

try:

    data = open('sketch.txt')

 

    for each_line in data:

        try:

            (role, line_spoken) = each_line.split(':')

            print(role, end='')

            print(' said ', end='')

            print(line_spoken, end='')

except ValueError:

            pass

 

data.close()

except IOError:

    print('파일이 없는 데?')

 

이렇게 하면 해당 에러만 처리하게 된다.


참고 : headfirst python


2014/06/11 - [파이썬] - [파이썬3.0] 파일 입출력


2014/04/26 - [파이썬] - [파이썬3.0]데이터 형 – 집합 – 기초


2014/04/26 - [파이썬] - [파이썬3.0]데이터 형 – 사전(dictionary) – 기초



댓글()