{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "***\n", "***\n", "# 23. 예외처리\n", "***\n", "***" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "***\n", "## 1 파이썬 예외의 종류\n", "***" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 구문 에러 (Syntax Error)\n", " - 문법적 에러\n", " - 이클립스 등의 통합개발환경 도구에서는 자동으로 실행 전에 구문 에러를 체크 해 줌\n", " - 파이썬은 상대적으로 언어적 문법이 간단하기 때문에 구문 자체의 에러 발생 비율이 낮으며, 통합개발환경 도구를 사용하여 완벽하게 제거할 수 있음\n", "\n", "- 논리 에러 (Logical Error)\n", " - 논리적 에러\n", " - 문법적 에러가 없으므로 프로그램이 실행이 되며, 비정상적으로 종료되지 않는 버그\n", " - 논리 오류는 즉시 인식되지는 않지만 의도치 않은 또는 바라지 않은 결과나 다른 행동을 유발\n", " \n", "- 예외 (Exception)\n", " - 문법적 에러는 없으나 프로그램 실행 중 더 이상 진행 할 수 없는 상황\n", " - 즉, 논리 에러에 해당함\n", " - 프로그램 실력은 이러한 예외 처리를 얼마나 꼼꼼하게 잘 하는가에 달려 있음" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 파이썬에서의 예외 (Exception) 종류\n", " - 에러 (Error)\n", " - 대부분의 예외\n", " - 대부분의 예외들에 해당하는 클래스 이름은 Error 로 끝남\n", " - 경고 (Warning)\n", " - 논리적인 오류로 판단하기에 애매한 상황\n", " - 일단은 무시하여도 좋음\n", " - 하지만, 미래에는 다른 판단을 하여 에러로 변경될 수 있음" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1-1 예외 발생 예제 보기\n", "- 예외 발생 예제 1: 정의되지 않은 변수 사용하기\n", " - NameError" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "ename": "NameError", "evalue": "name 'spam' is not defined", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;36m4\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mspam\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mNameError\u001b[0m: name 'spam' is not defined" ] } ], "source": [ "4 + spam*3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 예외 발생 예제 2: 0으로 숫자 나누기\n", " - ZeroDivisionError" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "ename": "ZeroDivisionError", "evalue": "division by zero", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0ma\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m10\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mc\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0ma\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mZeroDivisionError\u001b[0m: division by zero" ] } ], "source": [ "a = 10\n", "b = 0 \n", "c = a / b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- [note] 예외가 발생하면 프로그램은 바로 종료된다." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "ename": "ZeroDivisionError", "evalue": "float division by zero", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m10.0\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0mn\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mdivision\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m\u001b[0m in \u001b[0;36mdivision\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mdivision\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mn\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m5\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m10.0\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0mn\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mdivision\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mZeroDivisionError\u001b[0m: float division by zero" ] } ], "source": [ "def division():\n", " for n in range(0, 5):\n", " print(10.0 / n)\n", "\n", "division()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 예외 발생 예제 3: 문자열과 숫자 더하기\n", " - TypeError" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "must be str, not int", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;34m'2'\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mTypeError\u001b[0m: must be str, not int" ] } ], "source": [ "'2' + 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 예외 발생 예제 4: 참조 범위를 넘어서 인덱스 사용\n", " - IndexError" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "ename": "IndexError", "evalue": "list index out of range", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0ml\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ml\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mIndexError\u001b[0m: list index out of range" ] } ], "source": [ "l = [1, 2]\n", "print(l[2])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 예외 발생 예제 5: 등록되지 않은 키로 사전 검색\n", " - KeyError" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "ename": "KeyError", "evalue": "'c'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0md\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m\"a\"\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"b\"\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0md\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'c'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mKeyError\u001b[0m: 'c'" ] } ], "source": [ "d = {\"a\": 1, \"b\": 2}\n", "print(d['c'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 예외 발생 예제 6: 있지도 않은 파일을 열려고 할 때\n", " - FileNotFoundError (Python3)\n", " - IOError (Python2)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "ename": "FileNotFoundError", "evalue": "[Errno 2] No such file or directory: 'aaa.txt'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mFileNotFoundError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0ma\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mopen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'aaa.txt'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: 'aaa.txt'" ] } ], "source": [ "a = open('aaa.txt')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1-2 내장 예외의 종류\n", "- 예외 클래스의 계층 구조\n", " - python2: https://docs.python.org/2/library/exceptions.html\n", " - python3: https://docs.python.org/3/library/exceptions.html\n", "\n", "
BaseException\n",
    " +-- SystemExit\n",
    " +-- KeyboardInterrupt\n",
    " +-- GeneratorExit\n",
    " +-- Exception\n",
    "      +-- StopIteration\n",
    "      +-- StopAsyncIteration\n",
    "      +-- ArithmeticError\n",
    "      |    +-- FloatingPointError\n",
    "      |    +-- OverflowError\n",
    "      |    +-- ZeroDivisionError\n",
    "      +-- AssertionError\n",
    "      +-- AttributeError\n",
    "      +-- BufferError\n",
    "      +-- EOFError\n",
    "      +-- ImportError\n",
    "      |    +-- ModuleNotFoundError\n",
    "      +-- LookupError\n",
    "      |    +-- IndexError\n",
    "      |    +-- KeyError\n",
    "      +-- MemoryError\n",
    "      +-- NameError\n",
    "      |    +-- UnboundLocalError\n",
    "      +-- OSError\n",
    "      |    +-- BlockingIOError\n",
    "      |    +-- ChildProcessError\n",
    "      |    +-- ConnectionError\n",
    "      |    |    +-- BrokenPipeError\n",
    "      |    |    +-- ConnectionAbortedError\n",
    "      |    |    +-- ConnectionRefusedError\n",
    "      |    |    +-- ConnectionResetError\n",
    "      |    +-- FileExistsError\n",
    "      |    +-- FileNotFoundError\n",
    "      |    +-- InterruptedError\n",
    "      |    +-- IsADirectoryError\n",
    "      |    +-- NotADirectoryError\n",
    "      |    +-- PermissionError\n",
    "      |    +-- ProcessLookupError\n",
    "      |    +-- TimeoutError\n",
    "      +-- ReferenceError\n",
    "      +-- RuntimeError\n",
    "      |    +-- NotImplementedError\n",
    "      |    +-- RecursionError\n",
    "      +-- SyntaxError\n",
    "      |    +-- IndentationError\n",
    "      |         +-- TabError\n",
    "      +-- SystemError\n",
    "      +-- TypeError\n",
    "      +-- ValueError\n",
    "      |    +-- UnicodeError\n",
    "      |         +-- UnicodeDecodeError\n",
    "      |         +-- UnicodeEncodeError\n",
    "      |         +-- UnicodeTranslateError\n",
    "      +-- Warning\n",
    "           +-- DeprecationWarning\n",
    "           +-- PendingDeprecationWarning\n",
    "           +-- RuntimeWarning\n",
    "           +-- SyntaxWarning\n",
    "           +-- UserWarning\n",
    "           +-- FutureWarning\n",
    "           +-- ImportWarning\n",
    "           +-- UnicodeWarning\n",
    "           +-- BytesWarning\n",
    "           +-- ResourceWarning\n",
    "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "***\n", "## 2 예외 처리 방법\n", "***" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1-1 try/except/else/finally 절 사용하기\n", "- 예외가 발생할 수 있는 상황을 예상하여 예외 발생 상황을 전체 코드 흐름을 함께 제어할 수 있다.\n", "- try/except/else/finally 절\n", " - 구문\n", "> try:
\n", ">     (예외 발생 가능한) 일반적인 수행문들
\n", "> except Exception:
\n", ">     예외가 발생하였을 때 수행되는 문들
\n", "> else:
\n", ">     예외가 발생하지 않았을 때 수행되는 문들
\n", "> finally:
\n", ">     예외 발생 유무와 관계없이 무조건 수행되는 문들
" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "zero division error!!!\n" ] } ], "source": [ "try:\n", " print(1.0 / 0.0)\n", "except ZeroDivisionError:\n", " print('zero division error!!!')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 예외 처리를 하면 예외 발생시 프로그램 종료가 되지 않는다.\n", "- as 라는 구문을 통하여 예외 객체를 잡아서 처리할 수 있음." ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ZeroDivisionError 발생\n", "-----float division by zero\n", "-----float division by zero\n", "-----\n", "10.0\n", "5.0\n", "3.3333333333333335\n", "2.5\n" ] } ], "source": [ "#python3.x\n", "def division():\n", " for n in range(0, 5):\n", " try:\n", " print(10.0 / n)\n", " except ZeroDivisionError as e:\n", " print(\"ZeroDivisionError 발생\")\n", " print(\"-----\" + str(e))\n", " print(\"-----\" + e.__str__())\n", " print(\"-----\" + str(e.__class__))\n", "\n", "division()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- else: 구문은 except: 구문없이 사용 못한다. " ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "ename": "SyntaxError", "evalue": "invalid syntax (, line 5)", "output_type": "error", "traceback": [ "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m5\u001b[0m\n\u001b[0;31m else:\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" ] } ], "source": [ "def division():\n", " for n in range(0, 5):\n", " try:\n", " print(10.0 / n)\n", " else:\n", " print(\"Success\")\n", "\n", "division() " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 상황에 따라서는 에러와 함께 따라오는 정보를 함께 받을 수도 있다.\n", " - 그러한 정보를 얻으려면 객체 자체를 print()에 넣어 출력하면 됨" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Error - name 'spam' is not defined\n" ] } ], "source": [ "#python3.x\n", "try:\n", " spam()\n", "except NameError as e:\n", " print('Error -', e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- try 절 안에서 간접적으로 호출한 함수의 내부 예외는 그 함수를 호출한 쪽에서도 처리할 수 있다\n", " - 즉, 예외는 함수안에서 처리가 안되면 함수 밖으로 던져진다." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "zero division error!!! - division by zero\n" ] } ], "source": [ "#python3.x\n", "def zero_division():\n", " x = 1 / 0\n", "\n", "try:\n", " zero_division()\n", "except ZeroDivisionError as e:\n", " print('zero division error!!! -', e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 함수 안에서 예외 처리를 하면 함수를 호출한 쪽으로 해당 예외가 넘어오지 않는다." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Inner - zero division error!!! - division by zero\n" ] } ], "source": [ "#python3.x\n", "def zero_division():\n", " try:\n", " x = 1 / 0\n", " except ZeroDivisionError as e:\n", " print('Inner - zero division error!!! -', e)\n", "\n", "try:\n", " zero_division()\n", "except ZeroDivisionError as e:\n", " print('Outer - zero division error!!! -', e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- except 뒤에 아무런 예외도 기술하지 않으면 모든 예외에 대해 처리된다." ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Error\n" ] } ], "source": [ "try:\n", " spam()\n", " print(1.0 / 0.0)\n", "except:\n", " print('Error')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 여러 예외들 각각에 대해 except 절을 다중으로 삽입할 수 있다.\n", " - 하지만 해당 예외가 발생하면 그 다중으로 삽입된 except 중 하나만 처리된다." ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ZeroDivisionError !!!\n", "Exit !!!\n" ] } ], "source": [ "b = 0.0\n", "name = 'aaa.txt'\n", "try:\n", " print(1.0 / b)\n", " spam()\n", " f = open(name, 'r')\n", " '2' + 2\n", "except NameError:\n", " print('NameError !!!')\n", "except ZeroDivisionError:\n", " print('ZeroDivisionError !!!')\n", "except (TypeError, IOError):\n", " print('TypeError or IOError !!!')\n", "else:\n", " print('No Exception !!!')\n", "finally:\n", " print('Exit !!!')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 파일에서 숫자를 읽어와서 읽은 숫자로 나누기를 하는 예제\n", " - 꼼꼼한 예외 처리 예제" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ls: t.txt: No such file or directory\r\n" ] } ], "source": [ "%ls t.txt" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "/Users/yhhan/git/python-e-learning/python3.6\n", "[Errno 2] No such file or directory: 't.txt'\n" ] } ], "source": [ "#python3.x\n", "import os\n", "print(os.getcwd())\n", "filename = 't.txt'\n", "\n", "try:\n", " f = open(filename, 'r')\n", "except IOError as e:\n", " print(e)\n", "else:\n", " a = float(f.readline())\n", " try:\n", " answer = 1.0 / a\n", " except ZeroDivisionError as e:\n", " print(e)\n", " else:\n", " print(answer)\n", " finally:\n", " print(\"Finally!!!\")\n", " f.close()" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a.txt\r\n" ] } ], "source": [ "%ls a.txt" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.0" ] } ], "source": [ "%cat a.txt" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "/Users/yhhan/git/python-e-learning/python3.6\n", "[Errno 2] No such file or directory: 't.txt'\n", "float division by zero\n", "Finally!!!\n" ] } ], "source": [ "#python3.x\n", "import os\n", "print(os.getcwd())\n", "filename = 't.txt'\n", "default_filename = 'a.txt'\n", "try:\n", " f = open(filename, 'r')\n", "except IOError as e:\n", " print(e)\n", " f = open(default_filename, 'r')\n", "\n", "a = float(f.readline())\n", "try:\n", " answer = 1.0 / a\n", "except ZeroDivisionError as e:\n", " print(e)\n", "else:\n", " print(answer)\n", "finally:\n", " print(\"Finally!!!\")\n", " f.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2-2 같은 부류의 예외 다 잡아내기\n", "- 예외 클래스들은 상속에 의한 계층 관계를 지니고 있기 때문에 이를 이용하면 여러 예외들을 한꺼번에 잡을 수 있다.\n", "- 예를 들어, ArithmeticError의 하위 클래스로서 FloatingPointError, OverflowError, ZeroDivisionError가 존재하기 때문에 이들 하위 클래스 예외가 발생하였을 경우 ArithmeticError로서 잡아낼 수 있다. " ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ArithmeticException occured\n" ] } ], "source": [ "def dosomething():\n", " a = 1/0\n", "\n", "try:\n", " dosomething()\n", "except ArithmeticError:\n", " print(\"ArithmeticException occured\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 예외가 임의의 except에 의해 잡히면 다른 except에 의해서는 잡히지 않는다. " ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ZeroDivisionError occured\n" ] } ], "source": [ "def dosomething():\n", " a = 1/0\n", "\n", "try:\n", " dosomething()\n", "except ZeroDivisionError: # ZeroDivisionError는 이곳에서 잡힌다.\n", " print(\"ZeroDivisionError occured\")\n", "except ArithmeticError: # FloatingPointError, OverflowError는 이곳에서 잡힌다.\n", " print(\"ArithmeticException occured\")" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ArithmeticException occured\n" ] } ], "source": [ "def dosomething():\n", " a = 1/0\n", "\n", "try:\n", " dosomething()\n", "except ArithmeticError:\n", " print(\"ArithmeticException occured\")\n", "except ZeroDivisionError: # 이곳에서 ZeroDivisionError는 잡히지 않는다. ==> 잘못된 코드\n", " print(\"ZeroDivisionError occured\" ) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "***\n", "## 3 예외 발생\n", "***\n", "### 3-1 raise로 예외 발생하기" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 예외를 특정 상황 조건에서 raise 키워드를 통해 발생시킬 수 있다.\n", "- 아래 예는 시퀀스 형 클래스를 설계할 때 인덱싱을 구현하는 \\_\\_getitem\\_\\_ 메소드에서 인덱스가 범위를 넘을 때 IndexError를 발생시킨다." ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4 16\n", "0 1 4 9 16 25 36 49 64 81 " ] }, { "ename": "IndexError", "evalue": "", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 17\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mend\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\" \"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 19\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ms\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m20\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# 첨자 범위가 넘었다\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m\u001b[0m in \u001b[0;36m__getitem__\u001b[0;34m(self, k)\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__getitem__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mk\u001b[0m \u001b[0;34m>=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mn\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0mk\u001b[0m \u001b[0;34m<\u001b[0m \u001b[0;36m0\u001b[0m \u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 7\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mIndexError\u001b[0m \u001b[0;31m# 첨자 범위를 벗어나면 IndexError 예외를 발생시킴\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 8\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mk\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mIndexError\u001b[0m: " ] } ], "source": [ "class SquareSeq:\n", " def __init__(self, n):\n", " self.n = n\n", " \n", " def __getitem__(self, k):\n", " if k >= self.n or k < 0 :\n", " raise IndexError # 첨자 범위를 벗어나면 IndexError 예외를 발생시킴\n", " return k * k\n", "\n", " def __len__(self):\n", " return self.n\n", " \n", "s = SquareSeq(10)\n", "print(s[2], s[4])\n", "\n", "for x in s: # IndexError가 발생하는 시점까지 반복한다\n", " print(x,end=\" \")\n", "\n", "print(s[20]) # 첨자 범위가 넘었다" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 3-2 사용자 클래스 예외 정의 및 발생시키기\n", "- 사용자 정의 예외 클래스를 구현하는 일반적인 방법은 Exception 클래스를 상속 받아 구현한다.\n", " - Exception 클래스의 서브 클래스 중 하나를 상속 받아도 된다.\n", "- 사용자 정의 예외 발생 방법\n", " - 내장 예외 발생 방법과 동일하게 raise [클래스의 인스턴스] 와 같이 해당 예외 클래스의 인스턴스를 던진다.\n", "- 사용자 정의 예외를 잡는 방법\n", " - except [클래스 이름] 과 같이 해당 예외 클래스 이름을 사용한다.\n", "- 아래 예에서 except Big이 잡는 예외는 Big과 Small 이다.\n", " - 이유: Small은 Big의 하위 클래스이기 때문" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [], "source": [ "class Big(Exception):\n", " pass\n", "\n", "class Small(Big):\n", " pass" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Big Exception occurs!\n", "Big Exception occurs!\n" ] } ], "source": [ "def dosomething1():\n", " x = Big()\n", " raise x\n", " \n", "def dosomething2():\n", " raise Small()\n", " \n", "for f in (dosomething1, dosomething2):\n", " try:\n", " f()\n", " except Big:\n", " print(\"Big Exception occurs!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 3-3 예외값 전달하기 \n", "- raise 키워드 뒤에 예외와 함께, 추가 메시지를 함께 던질 수 있다. \n", " - python3에서는 지원하지 않음\n", "- python3에서는 예외의 생성자내에 메시지를 넣어서 예외 객체를 생성하여 던진다. " ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "message!!!\n" ] } ], "source": [ "#python3.x\n", "def f():\n", " raise Exception('message!!!')\n", " \n", "try:\n", " f()\n", "except Exception as e:\n", " print(e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 생성자 안에 넣어준 에러 메시지는 except 키워드 사용시에 두 번째 인자로 해당 메시지를 받을 수 있다.\n", " - python3에서는 지원하지 않음\n", "- python3에서는 예외 객체를 받아서..\n", " - 객체 자체를 print() 하거나\n", " - 해당 객체의 \\_\\_str\\_\\_()을 호출하여 메시지 문자열을 얻어서 print() 한다." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0으로 나누고 있습니다.\n" ] } ], "source": [ "#python3.x\n", "a = 10\n", "b = 0\n", "try:\n", " if b == 0:\n", " raise ArithmeticError('0으로 나누고 있습니다.')\n", " a / b\n", "except ArithmeticError as e:\n", " print(e)" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0으로 나누고 있습니다.\n" ] } ], "source": [ "#python2.x\n", "a = 10\n", "b = 0\n", "try:\n", " if b == 0:\n", " raise ArithmeticError('0으로 나누고 있습니다.')\n", " a / b\n", "except ArithmeticError, v:\n", " print v" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

참고 문헌: 파이썬(열혈강의)(개정판 VER.2), 이강성, FreeLec, 2005년 8월 29일

" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.4" } }, "nbformat": 4, "nbformat_minor": 1 }