with

파일 open, read는 이런식으로 사용한다.

```python

with open("foo.txt", "w") as f:

while True:

line = f.readline()

if not line: break

print(line)

```

auto close를 위해 with를 사용하는게 좋다. with를 빠져나오면서 자동으로 close한다.

파일에서 데이터를 읽어오는데 read(), readline(), readlines()  함수를 지원한다. readlines()는 각 라인을 리스트로 반환한다.

대신 try - finally로 finally에서 `` close()``를 호출해 주는 방법도 괜찮다.

간단한 open은 with로, 다른 메소드를 호출해야 하는 등의 나머지 경우는 finally로 처리한다.

 

try-except-else-finally

* 클래스 기반의 예외를 사용하는 것이 좋다.

 

```python

try:

    4 / 0

except ZeroDivisionError as e:

    print(e)

else:

    pass

finally:

    pass

```

else는 exception이 발생하지 않았을 때 실행된다.

finally는 exception 여부와 상관없이 항상 실행되므로 주로 여기서 자원반납 처리한다.

 

에러 회피

```python

except:

pass 

```

 

에러 강제 발생

```python

class Bird:

    def fly(self):

        raise NotImplementedError

```

* `` NotImplementedError``는 자식 클래스가 이 메소드를 오버라이딩 하지 않으면 에러를 발생시킨다.

 

사용자 정의 에러

사용자가 새로운 에러를 정의하려면 `` Exception`` 클래스를 상속받아 에러 클래스를 만들면 된다.

사용자 정의 에러가 발생했을 때,

 

```python

except UserError as e:

print(e)

```

에러를 받아 에러 메시지를 출력하도록 하기 위해서는 ``python __str__()`` 메서드를 구현해야 한다.

``python __str__()``메서드는 에러메시지를 출력할 경우 호출되는 메서드다.

```python

class UserError(Exception):

def __str__(self):

return "사용자 정의 에러"

```

 

``python __init__``도 사용할 수 있다. 따라서 ``python raise UserError("사용자 정의 에러")`` 처럼 에러를 던지면서 에러메시지를 정의할 수도 있다. 그래서 에러 메시지에 따라 에러를 여러개 정의하지 않고 하나만 정의한 다음 쓰는 지점에 따라 메시지를 다르게 줄 수 있다.