我正试图从这个doc了解python decorator。并且正在编写处理API异常所需的自己的装饰器。
但是在我的装饰器中,我没有得到如何在我的自定义装饰器中访问参数(method
,api
和data
)。
我知道,我没有把method
传递到任何地方,因为我没有到达哪里,所以我可以在我的装饰师中接受它。
这是我的装饰者:
import requests as r
import json
def handle_api_exceptions(http_api_call):
""" """
def wrapper(*args, **kwargs):
""" """
response = {}
try:
response = http_api_call(*args, **kwargs)
if response.ok:
result = response.json()
if result.get('code', 200) in INVALID_STATUS_CODES: #INVALID_STATUS_CODES = [1801, 1803, 1806,... ]
response = {"data":{}, "status":False}
else:
return result
else:
capture_failed_requests(method, api, data, response,
error=None, reason=response.reason)
return {}
except r.exceptions.ConnectionError as e:
capture_failed_requests(method, api, data, response, error=e,
reason="Connection Aborted")
return {}
except json.decoder.JSONDecodeError as e:
capture_failed_requests(method, api, data, response, error=e,
reason="Invalid Response")
return {}
except r.exceptions.ReadTimeout as e:
capture_failed_requests(method, api, data, response, error=e,
reason="Request Timed Out")
return {}
except Exception as e:
capture_failed_requests(method, api, data, response, error=e,
reason="Internal Server Error")
return {}
return wrapper
自定义GET,POST API请求:
@handle_api_exceptions
def get(self, api, data, token=None):
""" """
if token:data.update(self.get_token(token))
response = r.get(api, data, verify=self.config.SSL_VERIFY,
timeout=self.config.REQUEST_TIMEOUT)
return response
@handle_api_exceptions
def post(self, api, data, token=None):
""" """
if token:
data.update(self.get_secret_token(token))
response = r.post(api, data, verify=self.config.SSL_VERIFY,
timeout=self.config.REQUEST_TIMEOUT)
return response
def post_call(self):
""" """
api = "http://192.168.0.24/api/v1/reset/"
data = {"k1":[], "k2":{}, "id":123456} #-- Some Key val
return self.post(api, data, token="SOME_SECRET_TOKEN")
查询是:如何在method
中传递api
,data
和capture_failed_requests()
?
答案 0 :(得分:2)
data
和api
位于args
内wrapper
。 method
您必须单独提供,例如通过参数化装饰器(参见例如python decorators with parameters)。因此,您可以按如下方式执行此操作:
def handle_api_exceptions(method):
def decorator(http_api_call):
def wrapper(api, data, *args, **kwargs):
...
你的装饰会变得如此。
@handle_api_exceptions(method='GET')
def get(self, api, data, token=None):
...
或者,你可以使用method = http_api_call.__name__
(这会给你'get'
),并避免额外的嵌套和方法名重复。
请注意,我删除了空文档字符串 - 要么写一个实际的文档字符串(我喜欢Google-style,而是YMMV),要么根本没有。如果您的linting规则需要 docstrings,那是因为无论是谁设置它都希望您编写有用的,而不仅仅是欺骗它。