🎁
Box Python SDKでのAPI呼び出し時の標準エラーログ抑制
TL;DR
logging.getLogger(boxsdk.network.default_network.__name__).setLevel(logging.ERROR)
背景
例えば既に存在するフォルダを作成しようとすると409エラーとなるが、何もしないと強制的に標準エラーにエラーログが出力されてしまう。
example.py
import boxsdk.network.default_network
from boxsdk import BoxAPIException, Client, OAuth2
def main() -> None:
try:
client: Client = Client(
OAuth2(
client_id="***",
client_secret="***",
access_token="***",
refresh_token="***",
)
)
folder = client.folder("***").create_subfolder("***")
print("created", folder)
except BoxAPIException as e:
print("error", e.context_info)
if __name__ == "__main__":
main()
"POST https://api.box.com/2.0/folders" 409 303
{'date': '***, ** *** **** **:**:** GMT', 'content-type': 'application/json', 'x-envoy-upstream-service-time': '122', 'box-request-id': '***', 'cache-control': 'no-cache, no-store', 'strict-transport-security': 'max-age=31536000', 'via': '1.1 google', 'Alt-Svc': 'h3=":443"; ma=2592000,h3-29=":443"; ma=2592000', 'Transfer-Encoding': 'chunked'}
{'code': '---_use',
'context_info': {'conflicts': [{'etag': '***',
'id': '***',
'name': '***',
'sequence_id': '***',
'type': 'folder'}]},
'help_url': 'http://developers.box.com/docs/#errors',
'message': 'Item with the same name already exists',
'request_id': '****',
'status': 409,
'type': 'error'}
error {'conflicts': [{'type': 'folder', 'id': '***', 'sequence_id': '***', 'etag': '***', 'name': '***'}]}
自前でエラーログを出したい場合に重複して邪魔となり、かなり使いづらい。
確認したところ、boxsdk.network.default_network.DefaultNetworkResponse.log()
においてlogging
モジュールで出力していて、レスポンスがok
でないときにLogger
のログレベルを見て出力するか判定しているようである。
boxsdk/network/default_network.py
class DefaultNetworkResponse(NetworkResponse):
・・・
if self.ok:
logger_method, logger_level, response_format = self._logger.info, logging.INFO, self.SUCCESSFUL_RESPONSE_FORMAT
else:
logger_method, logger_level, response_format = self._logger.warning, logging.WARNING, self.ERROR_RESPONSE_FORMAT
if not self._logger.isEnabledFor(logger_level):
return
・・・
logger_method(
response_format,
{
'method': self.request_response.request.method,
'url': self.request_response.request.url,
'status_code': self.status_code,
'content_length': content_length,
'headers': pformat(self.headers),
'content': content,
},
)
何もしていない場合、logging.WARNING
は有効となっているようなのでlogger_method()
が呼ばれてしまい標準エラーが出力される。
対策
APIを呼び出すより前にDefaultNetworkResponse
で用いるLogger
のログレベルを変更し、logger_method()
が呼ばれないようにする。
コンストラクタでメンバに設定しているLogger
はgetLogger(__name__)
で、この__name__
の値はpython:boxsdk.network.default_network
である。
boxsdk/network/default_network.py
class DefaultNetworkResponse(NetworkResponse):
・・・
def __init__(self, request_response: 'Response', access_token_used: str, log_response_content: bool = True):
self._logger = getLogger(__name__)
以下のようにログレベルを先回りして書き換える。
example.py
from logging import ERROR, Logger, getLogger
import boxsdk.network.default_network
from boxsdk import BoxAPIException, Client, OAuth2
def main() -> None:
try:
logger: Logger = getLogger(boxsdk.network.default_network.__name__)
logger.setLevel(ERROR)
client: Client = Client(
OAuth2(
client_id="***",
client_secret="***",
access_token="***",
refresh_token="***",
)
)
folder = client.folder("***").create_subfolder("***")
print("created", folder)
except BoxAPIException as e:
print("error", e.context_info)
if __name__ == "__main__":
main()
error {'conflicts': [{'type': 'folder', 'id': '***', 'sequence_id': '***', 'etag': '***', 'name': '***'}]}
Discussion