파이썬 요청

시스템 설계 면접 질문 너무 개방적이어서 올바른 준비 방법을 알기가 너무 어렵습니다. 이제 구매 후 Amazon, Microsoft 및 Adobe의 디자인 라운드를 해독할 수 있습니다. 이 책은. 매일 수정 하나 디자인 질문 그리고 나는 당신이 디자인 라운드를 깨뜨릴 수 있다고 약속합니다.

Python에서 요청 HTTP 요청을 만드는 데 사용되는 내장 라이브러리입니다. 서비스와 상호 작용하고 데이터를 수집하는 방법에 집중할 수 있도록 간단한 API 뒤에 요청을 만드는 모든 복잡성을 숨깁니다.

요청 라이브러리에는 제공할 유용한 기능이 많이 있습니다. 이 자습서에서는 다양한 상황에 따라 사용자 정의되고 최적화된 방식으로 이러한 기능을 사용하는 방법을 살펴보겠습니다. 또한 요청을 효율적으로 사용하는 방법과 애플리케이션 속도를 저하시키는 외부 서비스에 대한 요청을 방지하는 방법을 배웁니다.

이 튜토리얼에서 배울 핵심 사항은 다음과 같습니다.

  • 가장 일반적인 HTTP 방법을 사용하여 요청하기
  • 쿼리 문자열과 메시지 본문을 사용하여 요청의 헤더 및 데이터 사용자 지정
  • 요청 및 응답에서 데이터 검사
  • 인증된 요청 만들기
  • 애플리케이션이 백업되거나 느려지지 않도록 요청을 구성하십시오.

HTTP에 대한 매우 기본적인 지식이 있다면 이 과정이 적합합니다. 그렇지 않은 경우에도 계속 따라할 수 있으므로 걱정하지 마십시오. 시작하자.

설치 요청:

세부 사항을 살펴보기 전에 요청 라이브러리를 설치해 보겠습니다.

터미널에 아래 명령을 입력하여 요청을 설치하십시오.

pip install requests

pipenv를 선호하는 경우 아래 명령을 사용하십시오.

pipenv install requests

설치가 완료되면 응용 프로그램에서 가져와서 사용하십시오.

import requests

이제 튜토리얼로 넘어가기 위한 모든 것이 준비되었습니다. GET 요청을 만들어 시작하겠습니다.

GET 요청:

GET 및 POST는 가장 널리 사용되는 HTTP 방법입니다. 이러한 메서드는 요청하는 동안 수행할 작업을 결정합니다. 예를 들어 웹 페이지에서 데이터를 가져오기 위해 GET을 사용하고 웹 페이지에 데이터를 게시하려면 POST를 사용합니다. 이 과정의 후반부에서 다른 HTTP 메소드를 다룰 것입니다.

GET 요청을 하려면 다음을 사용하십시오.

requests.get()

GitHub의 루트 나머지 API에 GET 요청을 하여 이를 테스트할 수 있습니다.

import requests
print(requests.get('https://api.github.com'))
<Response [200]>

첫 번째 GET 요청을 성공적으로 완료했습니다. 이제 요청에서 반환된 응답을 이해해야 합니다.

응답 :

HTTP 요청을 할 때마다 결과적으로 응답을 받습니다. 여기에는 요청의 성공 여부에 대한 정보가 포함됩니다. 응답 객체를 이해하려면 해당 속성과 동작을 살펴봐야 합니다.

그렇게 하려면 GET 요청을 하되 결과를 변수에 저장하십시오.

import requests
response=requests.get('https://api.github.com')

get()의 반환 값은 Response라는 변수에 저장하고 있는 Response의 인스턴스입니다. 이제 응답 변수를 사용하여 HTTP 요청의 결과를 수집할 수 있습니다.

상태 코드 :

HTTP 요청의 성공 여부를 알고 싶다면 상태 코드를 보면 됩니다. 상태 코드에는 요청 상태에 대한 정보가 포함됩니다.

예를 들어 상태 코드 200은 요청이 성공했음을 나타내고 404는 요청된 리소스를 찾을 수 없음을 나타냅니다. 살펴보기 상태 코드 목록 귀하의 요청 결과를 이해하기 위해. 씨

이전에 만든 GET 요청의 상태를 확인합니다. 다음을 통해 상태 코드를 얻을 수 있습니다.

>>> response.status_code
200

상태 코드는 200이며, 이는 GET 요청이 성공했으며 응답 개체에 요청된 정보가 포함되어 있음을 의미합니다.

응답에 따라 결정을 내려야 하는 상황에 직면할 수 있습니다.

if response.status_code==200:
    print('Request is Successful!')
elif response.status_code==404:
    print('Resource not found')

위의 코드는 응답의 상태 코드를 기반으로 콘솔에 적절한 메시지를 인쇄합니다.

요청 라이브러리는 위의 코드를 더욱 단순화합니다. 조건식에서 응답을 평가하는 경우 상태 코드가 200에서 400 사이이면 True를 반환하고 그렇지 않으면 False를 반환합니다.

조건식을 사용하여 위의 코드를 다시 작성해 보겠습니다.

if response:
    print('Request is Successful!')
else:
    print('There is an error')

여기에서 200에서 400 사이의 상태 코드를 확인합니다. 따라서 상태 코드 204 NO CONTENT(요청은 성공했지만 메시지 본문에 내용이 없음) 및 304 NOT MODIFIED도 성공한 것으로 간주됩니다.

따라서 일반적으로 요청이 성공적인지 확인하기 위해서만 이 단축 코드를 사용하십시오. 그런 다음 필요한 경우 상태 코드를 기반으로 요청을 처리합니다.

또한 .raise_for_status()를 사용하여 실패한 요청에 대한 예외를 발생시킵니다. 성공적인 응답의 경우 예외가 발생하지 않습니다.

import requests
from requests.exceptions import HTTPError

urls=[
    'https://api.github.com',
    'https://api.github.com/valid_api'
]
for url in urls:
    try:
        response=requests.get(url)
        response.raise_for_status()
    except HTTPError as http_error:
        print(f'There is an HTTP Error : {http_error}')
    except Exception as error:
        print(f'Some other error : {error}')
    else:
        print('Request is Successful!')

.raise_for_status() 메서드는 '요청이 성공했습니다!'를 반환합니다. 성공적인 요청에 대한 메시지. 특정 상태 코드의 경우 HTTPError가 발생할 수 있습니다.

콘텐츠 :

이제 우리는 상태 코드를 사용하여 요청 상태를 이해하는 방법을 알고 있습니다. 그러나 응답에는 더 많은 것이 있습니다. 실제로 응답 본문에서 서버가 다시 보낸 데이터를 볼 수 있습니다. 어떻게 하는지 봅시다.

응답에는 메시지 본문에 페이로드라는 중요한 정보가 포함되어 있습니다. 응답의 속성과 동작을 사용하여 다양한 형식의 페이로드를 볼 수 있습니다.

예를 들어 .content를 사용하여 응답 내용을 바이트 단위로 확인합니다.

response=requests.get('https://api.github.com')
print(response.content)
b'{"current_user_url":"https://api.github.com/user","current_user_authorizations_html_url":"https://github.com/settings/connections/applications{/client_id}","authorizations_url":"https://api.github.com/authorizations","code_search_url":"https://api.github.com/search/code?q={query}{&page,per_page,sort,order}","commit_search_url":"https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}"}'

UTF-8과 같은 문자 인코딩을 사용하여 응답 페이로드의 원시 바이트를 문자열로 변환하려는 경우 .text가 있으며 이 작업을 수행합니다.

>>> response.text
'{"current_user_url":"https://api.github.com/user","current_user_authorizations_html_url":"https://github.com/settings/connections/applications{/client_id}","authorizations_url":"https://api.github.com/authorizations","code_search_url":"https://api.github.com/search/code?q={query}{&page,per_page,sort,order}","commit_search_url":"https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}"}'

바이트에서 문자열로 변환하려면 인코딩 체계가 필요합니다. 인코딩 체계를 지정하지 않으면 요청은 응답의 헤더를 기반으로 하나를 추측합니다. .text를 사용하기 전에 .encoding을 명시적으로 설정할 수 있습니다.

>>> response.encoding='utf-8'
>>> response.text
'{"current_user_url":"https://api.github.com/user","current_user_authorizations_html_url":"https://github.com/settings/connections/applications{/client_id}","authorizations_url":"https://api.github.com/authorizations","code_search_url":"https://api.github.com/search/code?q={query}{&page,per_page,sort,order}","commit_search_url":"https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}"}'

응답 내용은 JSON 객체처럼 보입니다. 당신은 할 수 있습니다 문자열을 변환 json.loads() 또는 .json()을 사용하여 .text에서 JSON으로 가져옵니다.

>>> response.json()
{'current_user_url': 'https://api.github.com/user', 'current_user_authorizations_html_url': 'https://github.com/settings/connections/applications{/client_id}', 'authorizations_url': 'https://api.github.com/authorizations', 'code_search_url': 'https://api.github.com/search/code?q={query}{&page,per_page,sort,order}', 'commit_search_url': 'https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}'}

반환 값은 사전이므로 다음을 수행할 수 있습니다. 키를 사용하여 값에 액세스. 상태 코드와 메시지 본문으로 더 많은 작업을 수행할 수 있습니다. 그래도 응답의 메타데이터와 같은 추가 정보를 원하면 응답의 헤더를 확인해야 합니다.

응답 헤더:

응답 헤더에서 응답 페이로드의 유형 및 응답을 캐시하는 시간 제한과 같은 유용한 정보를 많이 얻을 수 있습니다.

>>> response.headers
{'date': 'Fri, 12 Jun 2020 09:03:08 GMT', 'content-type': 'application/json; charset=utf-8', 'server': 'GitHub.com', 'status': '200 OK', 'cache-control': 'public, max-age=60, s-maxage=60', 'vary': 'Accept, Accept-Encoding, Accept, X-Requested-With, Accept-Encoding', 'etag': 'W/"c6bac8870a7f94b08b440c3d5873c9ca"'}

반환된 값은 사전과 같은 객체이므로 키를 사용하여 값에 액세스할 수 있습니다. 예를 들어 응답 페이로드의 유형을 확인하기 위해 'content-type' 키에 대한 값을 얻을 수 있습니다.

>>> response.headers['content-type']
'application/json; charset=utf-8'

HTTP 사양은 헤더를 대소문자를 구분하지 않도록 정의합니다. 따라서 응답 헤더에 액세스하는 동안 케이스에 대해 걱정할 필요가 없습니다.

>>> response.headers['CONTENT-TYPe']
'application/json; charset=utf-8'

경우에 관계없이 반환 값은 동일하게 유지됩니다.

우리는 응답 객체의 유용한 속성과 동작을 다루었습니다. 이제 GET 요청을 사용자 지정하는 방법과 그에 따라 응답이 변경되는 방법을 살펴보겠습니다.

쿼리 문자열:

URL에서 쿼리 문자열의 매개변수에 값을 전달하는 것은 GET 요청을 사용자 정의하는 일반적인 방법 중 하나입니다. get() 메소드의 params에 값을 전달할 수 있습니다. 요청 라이브러리를 검색하는 예를 살펴보겠습니다. GitHub 저장소.

import requests

response = requests.get(
    'https://api.github.com/search/repositories',
    params={'q': 'requests+language:python'},
)

json_response=response.json()
respository_details=json_response['items'][0]
print(f'Name of the respository : {respository_details["name"]}')
print(f'Description of the repository : {respository_details["description"]}')

params에 전달된 값을 변경하여 응답 결과를 수정할 수 있습니다.

사전 유형의 매개변수에 데이터를 전달했습니다. 값을 전달할 수도 있습니다.

  • 튜플 목록:
response = requests.get(
    'https://api.github.com/search/repositories',
    params=[('q','requests+language:python')],
)
  • 바이트:
response = requests.get(
    'https://api.github.com/search/repositories',
    params=b'q=requests+language:python',
)

요청 헤더:

헤더를 추가하거나 수정하여 HTTP 요청을 사용자 정의할 수 있습니다. get() 메서드에서 값을 사전 형식으로 headers 매개변수에 전달합니다. Accept 헤더에서 media-type을 text-match로 지정하여 이전 요청과 일치하는 검색어를 강조 표시할 수 있습니다.

import requests

response = requests.get(
    'https://api.github.com/search/repositories',
    params={'q': 'requests+language:python'},
    headers={'Accept': 'application/vnd.github.v3.text-match+json'},
)

json_response=response.json()
respository_details=json_response['items'][0]
print(f'Matching items : {respository_details["text_matches"]}')

Accept 헤더는 서버에 애플리케이션이 처리하는 콘텐츠 유형을 알려줍니다. 값 'application/vnd.github.v3.text-match+json'은 독점적인 GitHub Accept 헤더이며 콘텐츠는 특수한 JSON 형식입니다.

다른 HTTP 방법:

앞서 언급했듯이 GET 외에도 POST, PUT, PATCH, DELETE, HEAD 및 OPTIONS와 같은 다른 인기 있는 HTTP 메서드가 있습니다.

>>> requests.post('https://httpbin.org/post', data={'key':'value'})
>>> requests.put('https://httpbin.org/put', data={'key':'value'})
>>> requests.delete('https://httpbin.org/delete')
>>> requests.head('https://httpbin.org/get')
>>> requests.patch('https://httpbin.org/patch', data={'key':'value'})
>>> requests.options('https://httpbin.org/get')

위에서 언급한 HTTP 메소드를 사용하여 httpbin 서비스에 요청을 하고 있습니다. GET 방식과 유사하게 각 방식에 대한 응답을 확인할 수 있습니다. 이러한 각 메서드에 대한 응답에는 헤더, 상태 코드 등이 포함됩니다.

헤드 및 삭제:

HEAD 메서드는 서버에서 헤더를 요청합니다.

>>> response = requests.head('https://httpbin.org/get')
>>> response.headers
{'Date': 'Sat, 13 Jun 2020 11:13:05 GMT', 'Content-Type': 'application/json', 'Content-Length': '308', 'Connection': 'keep-alive', 'Server': 'gunicorn/19.9.0', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Credentials': 'true'}

DELETE 메소드는 지정된 자원을 삭제합니다.

>>> response = requests.delete('https://httpbin.org/delete') 
>>> json_response=response.json() 
>>> json_response['args'] 
{}

POST, PUT 및 패치:

POST, PUT 및 PATCH 메서드는 메시지 본문을 통해 서버에 데이터를 게시합니다. 함수의 데이터 매개변수에 페이로드를 전달합니다.

POST 메서드는 새 리소스를 만드는 데 사용됩니다. PUT 및 PATCH는 각각 전체 및 부분 업데이트에 사용됩니다.

사전, 튜플 목록, 바이트 또는 파일류 객체의 데이터를 전달할 수 있습니다. 그만큼 데이터의 유형 우리가 필요로 하는 서비스의 특정 요구 사항에 따라 다릅니다. 예를 들어 요청의 콘텐츠 유형이 application/x-www-form-urlencoded인 경우 사전 형식으로 데이터를 보내야 합니다.

데이터 대신 json 매개변수를 사용하여 json 데이터를 보냅니다. 요청 라이브러리는 json 매개변수를 사용하는 동안 해당 콘텐츠 유형을 추가합니다. 요청에 대해 받은 응답에서 이를 확인할 수 있습니다.

import requests

response=requests.post('https://httpbin.org/post', json={'key':'value'})
json_response=response.json()
print(json_response['data'])
print(json_response['headers']['Content-Type'])
{"key": "value"}
application/json

준비된 요청:

요청 라이브러리는 대상 서버에 요청을 보내기 전에 헤더의 유효성을 검사하고 JSON 콘텐츠를 직렬화합니다. .request를 사용하면 이 PreparedRequest를 볼 수 있습니다. PreparedRequest는 페이로드, URL, 헤더 등과 같은 요청에 대한 정보를 제공합니다.

import requests

response=requests.post('https://httpbin.org/post', json={'key':'value'})
print(response.request.url)
print(response.request.headers)
print(response.request.body)
https://httpbin.org/post
{'User-Agent': 'python-requests/2.23.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '16', 'Content-Type': 'application/json'}
b'{"key": "value"}'

입증:

지금까지 공개 API에 인증되지 않은 요청을 보내는 방법을 살펴보았습니다. 그러나 서비스에서 인증을 요구할 수 있습니다. Authorization 헤더 또는 서버 정의 사용자 정의 헤더를 통해 자격 증명을 보냅니다. 요청 기능은 자격 증명을 전달하기 위해 auth 매개변수를 제공합니다.

GitHub의 내용을 살펴보자. 인증된 사용자 인증된 사용자의 프로필에 대한 정보를 제공하는 API입니다. Authenticated User API에 요청하기 위해 get()의 튜플에 사용자 이름과 비밀번호를 전달합니다.

import requests
from getpass import getpass

print(requests.get('https://api.github.com/user', auth=('username', getpass())))
<Response [200]>

요청이 성공하려면 유효한 자격 증명을 전달해야 합니다. 그렇지 않으면 401 승인되지 않은 오류가 발생합니다.

>>> requests.get('https://api.github.com/user')
<Response [401]>

사용자 이름과 비밀번호 요청을 전달할 때마다 HTTP를 사용하여 자격 증명이 적용됩니다. 기본 접근 인증 체계. 따라서 HTTPBasicAuth를 사용하여 자격 증명을 명시적으로 전달하여 위의 요청을 수정할 수 있습니다.

import requests
from getpass import getpass
from requests.auth import HTTPBasicAuth

print(requests.get('https://api.github.com/user', auth=HTTPBasicAuth('[email protected]', getpass())))
<Response [200]>

요청 라이브러리는 HTTPDigestAuth 및 HTTPProxyAuth와 같은 다른 인증 방법도 제공합니다.

AuthBase의 하위 클래스를 만들고 __call__() 메서드를 구현하여 사용자 지정 인증 메커니즘을 가질 수도 있습니다.

import requests
from requests.auth import AuthBase

class CustomTokenAuth(AuthBase):

    def __init__(self,token):
        self.token=token

    def __call__(self, request):
        request.headers['X-CustomTokenAuth']=f'{self.token}'
        return request

print(requests.get('https://httpbin.org/get', auth=CustomTokenAuth('sample_token123')))
<Response [200]>

여기에서 토큰을 받고 요청의 X-CustomTokenAuth 헤더에 추가합니다. 그러나 인증 메커니즘이 나쁘면 보안 취약점이 있습니다. 따라서 Basic 또는 OAuth와 같은 검증된 인증 체계를 고수하는 것이 항상 더 좋습니다.

SSL 인증서 확인:

웹 페이지에서 데이터를 주고받을 때 보안이 가장 중요합니다. HTTP를 통한 보안 사이트와의 통신은 대상 서버의 SSL 인증서를 확인하여 SSL을 사용하는 암호화된 연결에 의해 설정됩니다.

요청 라이브러리는 기본적으로 이 작업을 수행합니다. 확인 매개변수를 False로 전달하여 이 동작을 재정의할 수 있습니다. 요청은 또한 안전하지 않은 요청을 하고 있다는 경고를 제공합니다.

>>> requests.get('https://api.github.com', verify=False)
C:\Users\Gopi\AppData\Local\Programs\Python\Python36-32\lib\site-packages\urllib3\connectionpool.py:858: InsecureRequest
Warning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning)
<Response [200]>

성능 :

프로덕션 환경에서 요청을 사용할 때 성능을 관리해야 합니다. 애플리케이션을 문제 없이 계속 실행하려면 시간 초과 제어, 세션 및 재시도 제한을 처리해야 합니다.

제한 시간 :

외부 서비스에 요청하면 시스템은 응답을 기다립니다. 응답을 다시 받는 데 너무 오래 걸리면 사용자 환경이 좋지 않거나 백엔드 애플리케이션이 중단될 수 있습니다.

요청 라이브러리는 기본적으로 응답을 무기한 기다립니다. 그러나 timeout 매개변수를 사용하여 시간 초과 기간을 지정하여 이를 방지할 수 있습니다. 시간 초과는 시간 초과되기 전에 응답을 기다리는 시간(초)을 나타내는 정수 또는 부동 소수점 값을 허용합니다.

>>> requests.get('https://api.github.com', timeout=3)
<Response [200]>
>>> requests.get('https://api.github.com', timeout=4.5)
<Response [200]>

첫 번째 요청은 3초 후에 시간 초과되고 두 번째 요청은 4.5초 후에 시간 초과됩니다.

시간 초과는 튜플도 허용합니다. 첫 번째 값은 클라이언트가 연결을 설정하는 데 허용된 시간이고 두 번째 값은 연결이 설정된 후 응답을 기다리는 시간을 나타냅니다.

>>> requests.get('https://api.github.com', timeout=(3,4.5))
<Response [200]>

200초 이내에 연결이 설정되고 연결 설정 후 3초 이내에 응답이 수신되면 4.5 응답을 받게 됩니다. 요청 시간 초과의 Timeout 예외를 발생시킬 수도 있습니다.

import requests
from requests.exceptions import Timeout

try:
    response = requests.get('https://api.github.com', timeout=0.01)

except Timeout:
    print('Request timed out')
else:
    print('Request is successful')
Request timed out

세션 개체:

지금까지는 get() 및 post()와 같은 고수준 요청 API를 만들 때 연결이 설정되는 방식에 대해 걱정하지 않았습니다. 이러한 기능은 우리가 요청할 때 무슨 일이 일어나고 있는지에 대한 추상화일 뿐입니다. 이러한 추상화 아래에 세션이라는 클래스가 있습니다. 요청의 성능을 향상시키거나 요청을 제어하려면 세션의 인스턴스를 직접 사용해야 합니다.

요청 전반에 걸쳐 매개변수를 유지하기 위해 세션이 사용됩니다. 예를 들어 여러 요청에서 동일한 인증 자격 증명을 사용해야 하는 세션을 사용할 수 있습니다.

import requests
from getpass import getpass

with requests.Session() as session:
    session.auth = ('username', getpass())

    response = session.get('https://api.github.com/user')

print(response.headers)
print(response.json())

세션 개체가 인증 자격 증명으로 초기화되면 세션으로 요청할 때마다 자격 증명이 유지됩니다.

세션을 사용하여 연결을 만들 때마다 해당 연결을 연결 풀에 유지합니다. 동일한 연결이 다시 필요할 때 새 연결을 설정하는 대신 연결 풀의 연결을 다시 사용합니다. 따라서 성능은 지속적인 연결로 최적화됩니다.

최대 재시도:

요청이 실패했지만 애플리케이션이 재시도하기를 원하는 경우 ConnectionError가 발생합니다. 요청 라이브러리는 이 작업을 수행하지 않습니다. 솔루션은 사용자 지정 전송 어댑터를 구현하는 것입니다.

전송 어댑터를 사용하면 상호 작용하는 서비스별로 구성 집합을 정의할 수 있습니다. 예를 들어 https://api.github.com에 대한 모든 요청이 ConnectionError를 발생시키기 전에 5번 시도하기를 원합니다. 고유한 전송 어댑터를 빌드하고 max_retries 매개변수를 5배로 설정하고 기존 세션에 마운트합니다.

import requests
from requests.adapters import HTTPAdapter
from requests.exceptions import ConnectionError

transport_adapter = HTTPAdapter(max_retries=5)

session = requests.Session()

session.mount('https://api.github.com', transport_adapter)

try:
    session.get('https://api.github.com')
except ConnectionError as error:
    print(error)

Transport_adaptor를 세션 인스턴스에 마운트하면 세션 인스턴스가 https://api.github.com에 대한 각 요청에 대한 구성을 준수합니다.

 

균열 시스템 설계 인터뷰
Translate »