
타이틀을 "오류 메시지를 통해 본 파이썬"이라고 조금 거창하게 붙였다. 모든 컴퓨터 언어들이 컴파일하거나 실행할 때 에러가 발생하면 "어디서 무슨 에러가 났는지"에 대한 정보를 보여준다. 물론, 코드에 존재하는, 내가 미처 파악하지 못했던 에러를 찾는 (아주 감사한, 가끔은 너무 힘든) 기회를 제공하지만, 그와 별개로 컴퓨터 언어의 내부를 들여다 볼 수 있는 기회가 되기도 한다.
파이썬에서 흔히 보게 되는 몇가지 대표적인 오류 메시지와 해결방법에 대해서 한번 살펴보자.
○ NameError : name '-----' is not defined
가장 대표적인 에러로 NameError가 있다. (억지로 만든) 간단한 예를 한번 보자. 아래의 In[3]에서 Something 이라는 이름의 클래스를 하나 선언하고 있다. 그런데 In[6]에서 Something 객체를 하나 만들려고 하는데 보다시피 NameError가 발생하고 있다. 가장 아래에 있는 에러메시지가 가장 중요하다. NameError: name 'Someting' is not defined 라는 오류이다. Someting이라는 이름이 정의되어 있지 않다라는 뜻이다. 그리고, 그 위에 Traceback (most recent call last) 에서 이 에러가 어느 문장에서 생겼는지, 그리고 그 문장은 어디에서 호출되었는지를 거꾸로 쭈~욱 탐색해서 보여준다.

어쨌든 일단은 에러가 무엇인지를 파악하는 것이 중요한데 'Sonmeting'이라는 이름이 없다는 뜻이다. 파이썬에서 이름은 변수의 이름이거나, 함수의 이름이거나, 클래스의 이름이거나, 모듈 또는 패키지의 이름일 수 있다. 우리 문제의 경우에는 Something 이라고 쓰야 하는데 중간에 h를 빼먹고 Someting 이라고 씀으로써 생긴 에러이다. 어떻게 해결하면 되겠다? In[6]에서 s = Someting( )을 s= Something( )이라고 고치든지, 아니면 In[3]에서 class Something: 을 class Someting으로 바꿔주면 되겠다.
○ AttributeError : '----' object has no attribute '--'
위에서 살펴봤던 NameError와 유사한 에러로 AttributeError 가 있다. (또 억지로 만든) 간단한 예를 보자. 위의 Something 클래스가 정의되어 있는 상태에서 다음과 같이 명령어를 실행하면 AttributeError가 발생한다.

가장 아래에 있는 에러 메시지를 먼저 보자. 에러의 타입은 AttributeError이고 에러메시지는 'Something' objext has no attribute 'h' 로 나타나 있다. 무슨 뜻이다? 그 위에 Traceback을 보면 s.h( ) 문장에서 에러가 발생했는데 s 라는 이름의 Something 객체는 h 라는 이름의 속성 (변수 또는 함수를 말함) 을 가지고 있지 않다는 뜻이다. 우리 문제의 경우에 Something 객체는 h( ) 함수를 속성으로 가지고 있지 않다는 뜻이다.
이 에러에서 알 수 있듯이, 파이썬은 객체를 구성하는 변수와 함수를 모두 객체의 특성을 나타내는 속성 (attribute)라고 부른다는 것이다. 조금 구분해 본다면, 인스턴스 변수는 정적 속성 (static attribute), 메쏘드는 동적 속성(dynamic attribute) 쯤 되는 것으로 이해하면 좋겠다.
변수와 함수는 분명히 구별되는 것들인데, 왜 굳이 구분하지 않을까? 파이썬에서는 함수도 first class citizen 이라고 해서 변수와 똑같은 형태로 사용할 수가 있다. 변수가 사용되는 문장, 예를 들어 assignment나 함수의 인자로 함수를 넣을 수도 있다. 즉, 문장 상으로 보면 이 이름이 변수의 이름인지 함수의 이름인지 명확하게 드러나지 않는다는 의미에서 굳이 구분해서 사용하지 않는다. 속성이라는 이름으로 통일해서 부른다. 나중에 first class citizen에 대해서 한번 더 살펴볼 기회가 있을텐데, 일단은 아래의 코드 정도로 이해해 두자.

In[8]에서 f( )함수를 선언했다. In[9]에서 g = f 라는 명령어가 있는데 함수의 이름인 f가 어싸인먼트(=)의 우측 사이드(right side) 값이 되는, 조금은 낯선 명령어가 있다. 그냥 곧이 곧대로 해석하면, "f 를 g 라고 부르겠다" 는 것인데 실제 바로 아래에서 g( ) 함수가 호출되는 것을 확인할 수 있다. 더 재밌는 것은 함수의 이름을 다른 함수의 호출에 인자로 전달할 수 있다는 점이다. In[10]에서 h( )함수는 x 라는 인자를 받는데, 우리가 기대하는 것과는 다르게 x라는 인자가 x( ) 처럼 사용될 수 있다는 것이다. In[11]에서 h( )함수를 호출하면서 x 인자에 f 를 전달하였고 실제로 x = f 가 되면서 우리가 In[9]에서 봤던 결과와 동일한 결과가 발생하는 것을 확인할 수 있다.
○ IndexError: list index out of range
리스트 (보통의 컴퓨터 언어에서는 배열(array)이라고 부른다), 튜플과 같이 인덱스를 가지는 데이터 구조에서 참조할 수 없는 범위의 인덱스를 사용하는 경우에 발생하는 에러 메시지이다. 가장 아랫줄의 에러 메시지를 보면 list index out of range 가 있다. 여기서 out of range 라는 말의 의미가 참조할 수 있는 값의 범위(range)를 벗어났다(out of) 라는 의미이다. In[15]에서 data라는 리스트의 6번째 데이터인 data[5]를 참조하고자 하고 있는데, 실제 In[12]에서 정의된 data 리스트를 보면 전체 데이터의 개수가 5개여서 data[0]부터 data[1], data[2], data[3], data[4] 까지만 정의될 수 있는데 data 리스트에 존재하지 않는 데이터인 data[5]를 참조하고자 시도해서 생기는 에러이다. 물론, 거꾸로 인덱싱할 때 사용되는 음수 인덱스도 참조할 수 있는 range가 존재한다.

리스트의 인덱스는 0 부터 len(리스트 이름)-1 까지가 허용되는 범위(range)임을 항상 조심조심하기 바란다.
○ KeyError: '----'
리스트를 사용할 때의 에러가 IndexError라면, key-value 페어(pair)로 만들어지는 데이터 구조인 딕셔너리에서 가끔 보이는 에러가 KeyError이다. 아래의 예에서 보면, a라는 이름의 딕셔너리 객체는 'name'과 'age'라는 2개의 key 만 선언되어 있는데 In[18]에서 'res'라는 키에 해당하는 value를 참조하고자 시도하고 있다. 그에 따라 발생하는 KeyError: 'res' 는 현재 참조하려고 하는 딕셔너리 객체는 'res'라는 key를 가지고 있지 않다는 의미이다.

○ SyntaxError : Invalid Syntax
보통 구문 에러, 문법 에러라고 부르는 에러이다. 문장의 구성이 정해진 문법에 맞지 않다는 뜻이다. 영어의 예를 들어, 사람의 말에도 문법이 있다. 주어 다음에 동사가 와야 하고, 동사가 타동사이면 뒤에 반드시 목적어가 와야 한다. 목적어는 당연히 명사 또는 이에 준하는 명사구, 명사절이 되어야 한다. 뭐 그런 것들. 우리가 영어 문법 공부하면서 수차례 정리하고 외웠던 것들이다. 문법이란 것이 여러개의 단어를 나열해서 하나의 문장을 만드는데 필요한 규칙이라고 한다면, 문법에 맞지 않다(Syntax Error)는 것은 그러한 규칙에 맞지 않는 단어(또는 문자/문자열)가 사용되었다는 의미이다. 예를 들어, 콤마(,)를 쓰야 할 곳에 마침점(.)을 쓴다거나 아래와 같이 딕셔너리의 선언에는 전혀 기대되지 않는 세미콜론( ; )이 뜬금없이 포함되는 경우에 생기는 에러이다. 친절하게, 몇번째 line의 명령어 중에 어디에서 (아래의 삿갓( ^ ) 표시에 유의) 기대되지 않는 문자(열)가 있는지를 보여주니 참고해서 수정하면 되겠다.

○ 그럼, 도대체 얼마나 많은 에러가?
이쯤 되니까, 도대체 파이썬에서 다루어지는 에러에는 어떤 것들이 있는지가 궁금해 진다. 파이썬 홈페이지(https://docs.python.org/3/library/exceptions.html) 에 방문해 보면 Built-in Exceptions 라는 타이틀로 파이썬의 모든 에러 메시지에 대해 나열해 놓고 있다. 한두줄의 정의 정도의 설명 만 있어서 크게 도움은 안되는데, 그냥 "와, 많구나" 하면 되는 것이고 에러를 Exception (보통, 예외 또는 예외상황으로 번역함) 이라고도 부르는구나 하면 좋겠다. 단, 이제 부터는 에러가 생기면 일단 에러의 이름부터 확인하고 에러 메시지를 통해 어떤 에러인지를 거꾸로 유추해 보는 습관을 가져 보는 것으로 하자.
** 자세한 내용은 [파이썬 알고리즘 객체지향 코딩의 기술]을 참고하기 바랍니다 **
'파이썬 (python)' 카테고리의 다른 글
[Python 34] 파이썬의 matplotlib와 예제 (0) | 2020.07.30 |
---|---|
[Python 32] 객체 : Encapsulation (0) | 2020.07.18 |
[Python 31] 코딩, 이것만 알자 (1) | 2020.07.18 |
[python 25] 파이썬 1부, 알고리즘 편을 끝내며 (0) | 2020.05.07 |
[python 24] 알고리즘 연습 - 4 : 두번째로 큰 값 찾기 (0) | 2020.04.25 |