如何干净地处理嵌套的try / excepts?

时间:2016-12-01 15:27:21

标签: python

我有一个方法可以提取有关特定gerrit版本的信息,并且它可以存在两个可能的端点。给出以下样本值:

revision_id = rev1
change_id = chg1
proj_branch_id = pbi1

修订版可以在

下生效
/changes/ch1/revisions/rev1/commit

/changes/pbi1/revisions/rev1/commit

我正在尝试使用最少的代码重复使用,如下所示:

@retry(
    wait_exponential_multiplier=1000,
    stop_max_delay=3000
)
def get_data(
        self,
        api_obj: GerritAPI,
        writer: cu.LockingWriter = None,
        test: bool = False
):
    """
    Make an HTTP Request using a pre-authed GerritAPI object to pull the
    JSON related to itself.  It checks the endpoint using just the change
    id first, and if that doesn't return anything, will try the endpoint
    using the full id.  It also cleans the data and adds ETL tracking
    fields.

:param api_obj: An authed GerritAPI object.
:param writer: A LockingWriter object.
:param test: If True then the data will be returned instead of written
 out.

:raises: If an HTTP Error occurs, an alternate endpoint will be
 attempted.  If this also raises an HTTP Error then the error is
 re-raised and propagated to the caller.
"""
logging.debug('Getting data for a commit for {f_id}'.format(
    f_id=self.proj_branch_id
))
endpoint = (r'/changes/{c_id}/revisions/{r_id}/commit'.format(
    c_id=self.change_id,
    r_id=self.revision_id
))
try:
    data = api_obj.get(endpoint)
except HTTPError:
    try:
        endpoint = (r'/changes/{f_id}/revisions/{r_id}/commit'.format(
            f_id=self.proj_branch_id,
            r_id=self.revision_id
        ))
        data = api_obj.get(endpoint)
    except HTTPError:
        logging.debug('Neither endpoint returned data: {ep}'.format(
            ep=endpoint
        ))
        raise
    else:
        data['name'] = data.get('committer')['name']
        data['email'] = data.get('committer')['email']
        data['date'] = data.get('committer')['date']
        mu.clean_data(data)
except ReadTimeout:
    logging.warning('Read Timeout occurred for a commit.  Endpoint: '
                    '{ep}'.format(ep=endpoint))
else:
    data['name'] = data.get('committer')['name']
    data['email'] = data.get('committer')['email']
    data['date'] = data.get('committer')['date']
    mu.clean_data(data)
finally:
    try:
        data.update(self.__dict__)
    except NameError:
        data = self.__dict__
    if test:
        return data
    mu.add_etl_fields(data)
    self._write_data(data, writer)

我不太喜欢我正在重复else下的部分,所以我想知道是否有办法更清洁地处理这个问题?作为旁注,就目前而言,如果它返回HTTPError,我的程序将为每次提交最多写出3次,正在创建一个实例变量self.written,用于跟踪它是否已被写出这是一种最佳实践方法吗?

0 个答案:

没有答案