파이썬 요청 모듈 사용을 시도 / 제외하는 올바른 방법?


답변:


794

요청 예외 문서를 살펴보십시오 . 한마디로 :

네트워크 문제 (예 : DNS 실패, 연결 거부 등)가 발생하면 요청에서 ConnectionError예외 가 발생합니다.

드문 잘못된 HTTP 응답의 경우 요청에서 HTTPError예외 가 발생합니다.

요청 시간이 초과되면 Timeout예외가 발생합니다.

요청이 구성된 최대 리디렉션 수를 초과하면 TooManyRedirects예외가 발생합니다.

요청이 명시 적으로 제기하는 모든 예외는에서 상속됩니다 requests.exceptions.RequestException.

당신의 질문에 답하기 위해, 당신이 보여주는 것이 모든 기초를 다룰 수 는 없습니다 . 시간 초과 오류가 아닌 연결 관련 오류 만 포착합니다.

예외를 잡을 때해야 할 일은 실제로 스크립트 / 프로그램 디자인에 달려 있습니다. 종료해도 괜찮습니까? 계속해서 다시 시도 할 수 있습니까? 오류가 치명적이며 계속 진행할 수 없다면, 예, SystemExit (오류를 인쇄하고 호출하는 좋은 방법)를 발생시켜 프로그램을 중단 할 수 있습니다 sys.exit.

모든 경우를 처리하는 기본 클래스 예외를 잡을 수 있습니다.

try:
    r = requests.get(url, params={'s': thing})
except requests.exceptions.RequestException as e:  # This is the correct syntax
    raise SystemExit(e)

또는 개별적으로 잡아서 다른 일을 할 수 있습니다.

try:
    r = requests.get(url, params={'s': thing})
except requests.exceptions.Timeout:
    # Maybe set up for a retry, or continue in a retry loop
except requests.exceptions.TooManyRedirects:
    # Tell the user their URL was bad and try a different one
except requests.exceptions.RequestException as e:
    # catastrophic error. bail.
    raise SystemExit(e)

그리스도인이 지적한 대로 :

http 오류 (예 : 401 Unauthorized)가 예외를 발생 시키도록하려면을 호출 할 수 있습니다 Response.raise_for_status. 그건를 올릴 것이다 HTTPError응답이 HTTP 오류 인 경우.

예를 들면 :

try:
    r = requests.get('http://www.google.com/nothere')
    r.raise_for_status()
except requests.exceptions.HTTPError as err:
    raise SystemExit(err)

인쇄합니다 :

404 Client Error: Not Found for url: http://www.google.com/nothere

11
요청 라이브러리의 세부 사항 및 일반적인 예외 포착을 처리하는 데 매우 적합한 답변입니다.
Brian Peterson

10
기본 urllib3 라이브러리의 버그로 인해 socket.timeout시간 초과 ( github.com/kennethreitz/requests/issues/1236
jb)를

15
미래의 의견 독자 : 이것은 요청 2.9에서 수정되었습니다 (urllib3 1.13 번들)
RazerM

14
http 오류 (예 : 401 Unauthorized)가 예외를 발생 시키도록하려면 Response.raise_for_status 를 호출 할 수 있습니다 . 응답이 http 오류 인 경우 HTTPError가 발생합니다.
Christian Long

5
요청 웹 사이트 의 예외 목록 이 완료되지 않았습니다. 여기 에서 전체 목록을 읽을 수 있습니다 .
Epoc

87

명시 적으로 하나 더 제안. 원하는 오류를 잡기 위해 특정 오류에서 일반 오류로 넘어가는 것이 가장 좋습니다. 따라서 특정 오류는 일반 오류에 의해 가려지지 않습니다.

url='http://www.google.com/blahblah'

try:
    r = requests.get(url,timeout=3)
    r.raise_for_status()
except requests.exceptions.HTTPError as errh:
    print ("Http Error:",errh)
except requests.exceptions.ConnectionError as errc:
    print ("Error Connecting:",errc)
except requests.exceptions.Timeout as errt:
    print ("Timeout Error:",errt)
except requests.exceptions.RequestException as err:
    print ("OOps: Something Else",err)

Http Error: 404 Client Error: Not Found for url: http://www.google.com/blahblah

vs

url='http://www.google.com/blahblah'

try:
    r = requests.get(url,timeout=3)
    r.raise_for_status()
except requests.exceptions.RequestException as err:
    print ("OOps: Something Else",err)
except requests.exceptions.HTTPError as errh:
    print ("Http Error:",errh)
except requests.exceptions.ConnectionError as errc:
    print ("Error Connecting:",errc)
except requests.exceptions.Timeout as errt:
    print ("Timeout Error:",errt)     

OOps: Something Else 404 Client Error: Not Found for url: http://www.google.com/blahblah

이 유효한 구문은 게시물입니까?
ScipioAfricanus

@ScipioAfricanus 네.
andrea

10

예외 객체에는 원래 response가 포함되어 e.response있어 서버의 응답으로 오류 본문을보아야 할 경우 유용 할 수 있습니다. 예를 들면 다음과 같습니다.

try:
    r = requests.post('somerestapi.com/post-here', data={'birthday': '9/9/3999'})
    r.raise_for_status()
except requests.exceptions.HTTPError as e:
    print (e.response.text)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.