【问题标题】:How to reduce to just one try,except statements如何减少到只有一次尝试,除了语句
【发布时间】:2018-11-28 12:45:53
【问题描述】:

我有一本包含多个 try-except 语句的字典。 我试图用 r.get() 检索值,但它给我抛出了一个带有 NoneObject 的类型错误。我知道 .get() 的默认参数是 None,但它不起作用。我有多个列表,我在每次迭代时附加来自不同字典值的数据。

如何将代码简化为单个 try-except 语句?谢谢!

这是我的代码:

for num in issue_number:
    print(num)
    Response = requests.get(f'https://example.com/rest/api/2/issue/Proj-{num}?expand=changelog&maxResults =1000', auth=(example))
    r = Response.json()
    try:
        task_list.append(r['key'])
    except TypeError:
        task_list.append('NA')
    try:
        summary_list.append(r['fields']['summary'])
    except TypeError:
        summary_list.append('NA')
    try:
        assignee_list.append(r['fields']['assignee']['displayName'])
    except TypeError:
        assignee_list.append('NA')
    try:
        created_list.append(r['fields']['created'])
    except:
        created_list.append('NA')
    try:
        status_list.append(r['fields']['status']['name'])
    except:
        status_list.append('NA')
    try:
        due_date_list.append(r['fields']['duedate'])
    except:
        due_date_list.append('NA')
    try:
        resolution_list.append(r['fields']['resolution']['name'])
    except:
        resolution_list.append('NA')
    try:
        resolution_date_list.append(r['fields']['resolutiondate'])
    except:
        resolution_date_list.append('NA')

【问题讨论】:

  • 你的回复是rNone吗?
  • 你好@doctorlove!不,对 r 的响应是一个包含 5 个字典的大字典。

标签: python request try-except


【解决方案1】:

您可以通过链接多个get 调用来避免所有这些:

for num in issue_number:
    print(num)
    Response = requests.get(f'https://example.com/rest/api/2/issue/Proj-{num}?expand=changelog&maxResults =1000', auth=(example))
    r = Response.json()
    task_list.append(r.get('key', 'NA'))
    summary_list.append(r.get('fields', {}).get('summary', 'NA'))
    assignee_list.append(r.get('fields', {}).get('assignee', {}).get('displayName','NA'))
    created_list.append(r.get('fields', {}).get('created', 'NA'))
    status_list.append(r.get('fields', {}).get('status', {}).get('name', 'NA'))
    due_date_list.append(r.get('fields', {}).get('duedate', 'NA'))
    resolution_list.append(r.get('fields', {}).get('resolution', {}).get('name', 'NA'))
    resolution_date_list.append(r.get('fields', {}).get('resolutiondate', 'NA'))

但是,由于您多次执行相同的操作,您可能会发现为此使用函数更方便,例如:

def get_deep(d, *keys, default=None):
    for k in keys:
        if not d or k not in d:
            # Stop early if a key is not found
            return default
        d = d[k]
    return d if d is not None else default

# ...

for num in issue_number:
    print(num)
    Response = requests.get(f'https://example.com/rest/api/2/issue/Proj-{num}?expand=changelog&maxResults =1000', auth=(example))
    r = Response.json()
    task_list.append(get_deep(r, 'key', default='NA'))
    summary_list.append(get_deep(r, 'fields', 'summary', default='NA'))
    assignee_list.append(get_deep(r, 'fields', 'assignee', 'displayName', default='NA'))
    created_list.append(get_deep(r, 'fields', 'created', default='NA'))
    status_list.append(get_deep(r, 'fields', 'status', 'name', default='NA'))
    due_date_list.append(get_deep(r, 'fields', 'duedate', default='NA'))
    resolution_list.append(get_deep(r, 'fields', 'resolution', 'name', default='NA'))
    resolution_date_list.append(get_deep(r, 'fields', 'resolutiondate', default='NA'))

【讨论】:

  • 你打败了我,只是在输入这个解决方案!
  • 你好@JoshuaNixon。谢谢!不幸的是,它返回一个错误:文件“”,第 3 行,如果 k 不在 d 中,则在 get_deep 中:TypeError:'NoneType' 类型的参数不可迭代
  • @user7362809 啊,我知道我没有意识到你可以有中间的None 值。看看更新的版本是否适合你...
【解决方案2】:

我倾向于将这类代码重构为:

from collections import namedtuple

Issue = namedtuple('Issue', [
  'task_key', 'summary', 'assignee', 'created'
])

import logging
logger = logging.getLogger(__name__)

def get_issue(num):
  res = requests.get(f'https://example.com/rest/api/2/issue/Proj-{num}?expand=changelog&maxResults=1000', auth=(example))
  res.raise_for_status()
  r = res.json()
  return Issue(
    r['key'], r['fields']['summary'],
    r['fields']['assignee']['displayName'],
    r['fields']['created'],
  )

issues = {}
for num in issue_number:
  try:
    issues[num] = get_issue(num)
  except:
    logger.exception("unable to process issue %s", num)

如果您真的想获得部分条目,那么使用来自@jdehesa 的get_deep 可能会有用

【讨论】:

    【解决方案3】:

    您可以将您的密钥作为元组存储在某个列表中,然后检查这些密钥对是否存在于 r 中,如果存在,请将它们添加到您的 status_list

    necessary_keys = [('key'), ('fields', 'summary'), ('fields', 'assignee', 'displayName'),
                      ('fields', 'created'), ('fields', 'status', 'name'),
                      ('fields', 'duedate'), ('fields', 'resolution', 'name'),
                      ('fields', 'resolutiondate')]
    
    def check_keys(dict_, keys):
        if keys[0] in dict_:
            if len(keys) == 1:
                return dict_[keys[0]]
            else:
                return check_keys(dict_[keys[0]], keys[1:])
        return 'NA'
    
    issue_number = [0]
    status_list = []
    
    for num in issue_number:
        print(num)
        #Response = requests.get(f'https://example.com/rest/api/2/issue/Proj-{num}?expand=changelog&maxResults =1000', auth=(example))
        #r = Response.json()
        r = {'fields': {'summary': 'test1', 'status': {'name': 'test2'}}}
    
        for key in necessary_keys:
            status_list.append(check_keys(r, key))
        print(status_list)
    

    输出:

    ['NA', 'test1', 'NA', 'NA', 'test2', 'NA', 'NA', 'NA']
    

    【讨论】:

      【解决方案4】:

      您可以使用字典来避免可变数量的变量。此外,您可以使用functools.reduce 来迭代嵌套字典。这是一个完整的例子:

      from collections import defaultdict
      from functools import reduce
      from operator import getitem
      
      def getitem_from_dict(dataDict, mapList):
          """Iterate nested dictionary"""
          return reduce(getitem, mapList, dataDict)
      
      d = {1: {'key': 'key1', 'fields': {'summary': 'summary1'}},
           2: {'key': 'key2', 'fields': {'summary': 'summary2'}},
           3: {'key': 'key3', 'fields': {'summary': 'summary3'}}}
      
      res = defaultdict(list)
      
      lsts = ['task', 'summary']
      keys = [['key'], ['fields', 'summary']]
      
      for num in [1, 2, 3]:
          r = d[num]
          for lst, key in zip(lsts, keys):
              try:
                  res[lst].append(getitem_from_dict(r, key))
              except TypeError:
                  res[lst].append('NA')
      
      print(res['task'])
      
      # ['key1', 'key2', 'key3']
      
      print(res['summary'])
      
      # ['summary1', 'summary2', 'summary3']
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-16
        • 2011-08-31
        • 2022-11-03
        • 2016-02-28
        • 2010-10-14
        • 1970-01-01
        相关资源
        最近更新 更多