异常排查

在使用DeepFOS时,可能会遇到一些异常信息。

本章节将介绍DeepFOS的常见异常类型,异常的排查方法等等,以便于您快速定位异常来源。

异常类型

本文将使用DeepFOS包的常见异常类型分为以下几类:

  1. 网络异常

  2. 外部API调用异常

  3. Python内建异常及DeepFOS的Bug引发的异常

  4. DeepFOS主动抛出异常

接下来将针对这些异常类型,列举典型的报错信息,以及可能导致该异常的原因。

网络异常

这类异常通常在本地调试时出现,并且报错有明显特征,一般会出现 Connection, Timeout 等字样。

造成这类报错的原因可能有:

1. 使用了VPN

您使用的环境的域名可能不能被国外的DNS服务器解析,因此如果您使用了VPN,可能导致无法访问某些环境。

典型报错

出现 check_host_name 字样。

解决方案

关闭VPN。

2. 没有在代码入口最上方import debug文件

为了能够在本地调试, debug文件 中进行了各种环境的预配置,如果没有导入debug文件, 或者在导入debug文件前已经导入了deepfos的模块,很可能导致预配置无法生效。

典型报错

Traceback (most recent call last):
  File "C:\Work\deepfos\_local_test\test1.py", line 10, in <module>
    dim = Dimension('tttt')
  File "C:\Work\deepfos\deepfos\element\dimension.py", line 81, in __init__
    super().__init__(element_name, folder_id, path)
  File "C:\Work\deepfos\deepfos\element\base.py", line 47, in __init__
    ele_detail = self.init_element()
  File "C:\Work\deepfos\deepfos\element\base.py", line 53, in init_element
    ele_info = self.get_element_info()
  File "C:\Work\deepfos\deepfos\element\base.py", line 78, in get_element_info
    ele_list = api.elements.get_element_info_by_name(ele_name, ele_type)
  File "C:\Work\deepfos\deepfos\api\base.py", line 337, in sync_call
    raise exc from None
deepfos.exceptions.APIRequestError: HTTPConnectionPool(host='app-server', port=80): Max retries exceeded with url: /elements/get-element-info-by-name/base-info?elementName=tttt&elementType=DIM (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x000002035802AF70>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed'))

报错内容的最后一行 HTTPConnectionPool(host='app-server', port=80) 提示您访问了域名为 app-server 的地址, 这代表 debug文件 配置的 host 没有生效。

解决方案

请参考“ 如何让本地代码和线上代码一致 ”,修改主入口文件。

3. 没有有效的网络连接

DeepFOS包要求在有有效网络连接的环境运行,必须确保您的电脑能够正确访问先胜云系统。

典型报错

Traceback (most recent call last):
  File "C:\Work\deepfos\_local_test\test1.py", line 11, in <module>
    dim = Dimension('tttt')
  File "C:\Work\deepfos\deepfos\element\dimension.py", line 81, in __init__
    super().__init__(element_name, folder_id, path)
  File "C:\Work\deepfos\deepfos\element\base.py", line 47, in __init__
    ele_detail = self.init_element()
  File "C:\Work\deepfos\deepfos\element\base.py", line 53, in init_element
    ele_info = self.get_element_info()
  File "C:\Work\deepfos\deepfos\element\base.py", line 78, in get_element_info
    ele_list = api.elements.get_element_info_by_name(ele_name, ele_type)
  File "C:\Work\deepfos\deepfos\api\base.py", line 337, in sync_call
    raise exc from None
deepfos.exceptions.APIRequestError: HTTPSConnectionPool(host='alpha.deepfos.com', port=443): Max retries exceeded with url: /seepln-server/app-server/elements/get-element-info-by-name/base-info?elementName=tttt&elementType=DIM (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x000002114EA52160>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed'))

报错内容和 上一节 的报错十分相似,但是host的内容不再是形如 app-server 的无效域名,说明您的配置生效, 但是您的电脑不能访问先胜云系统。

解决方案

切换到有有效网络连接的环境

外部API调用异常

DeeFOS SDK封装了几乎所有组件的常用restful API,由于网络请求的不确定性,调用则这些API可能会出现异常

提示

本小节的 “外部API” 指的是先胜云系统的组件API,外部是相对于DeepFOS SDK而言的。

DeepFOS SDK把这类异常分为两大类

  • 请求异常: APIRequestError

  • 响应异常: APIResponseError

1. 请求异常

请求异常发生在发送HTTP请求过程中,通常连接超时,服务无效等会导致这类错误。

出现这类错误说明请求没有到达服务端,可能需要检查网络连接和组件服务的有效性。

典型报错

Traceback (most recent call last):
  File "C:\Work\deepfos\_local_test\test1.py", line 11, in <module>
    dim = Dimension('tttt')
  File "C:\Work\deepfos\deepfos\element\dimension.py", line 81, in __init__
    super().__init__(element_name, folder_id, path)
  File "C:\Work\deepfos\deepfos\element\base.py", line 47, in __init__
    ele_detail = self.init_element()
  File "C:\Work\deepfos\deepfos\element\base.py", line 53, in init_element
    ele_info = self.get_element_info()
  File "C:\Work\deepfos\deepfos\element\base.py", line 78, in get_element_info
    ele_list = api.elements.get_element_info_by_name(ele_name, ele_type)
  File "C:\Work\deepfos\deepfos\api\base.py", line 337, in sync_call
    raise exc from None
deepfos.exceptions.APIRequestError: HTTPSConnectionPool(host='alpha.deepfos.com', port=443): Max retries exceeded with url: /seepln-server/app-server/elements/get-element-info-by-name/base-info?elementName=tttt&elementType=DIM (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x000002114EA52160>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed'))

解决方案

  1. 检查网络连接是否有效

  2. 检查请求的接口是否可以正常访问

2. 响应异常

响应异常发生在解析服务端的HTTP响应过程中。下述任何情况都可能导致响应异常:

  1. HTTP状态码非2xx

  2. 返回内容无法解析为JSON

  3. 返回的JSON缺少必须字段: status, data

  4. status字段值为 False

  5. 返回的JSON无法依据Model定义反序列化

典型报错 - 1

2021-08-17 18:27:04.230 | WARNING  | deepfos.api.base:parse_reponse:422 - Call api: https://alpha.deepfos.com/seepln-server/dimension-server1-0/dimension/query/select-dimension-member-by-name-function failed. Bad response because status is False. Detail: {"status":false,"data":null,"code":999999,"message":"维度表达式不正确"}
2021-08-17 18:27:04.230 | WARNING  | deepfos.api.base:check_response:511 - curl -X POST -H 'Accept: */*' -H 'Accept-Encoding: gzip, deflate' -H 'Connection: keep-alive' -H 'Content-Length: 333' -H 'Content-Type: application/json;charset=UTF8' -H 'User-Agent: python-requests/2.25.1' -H 'app: ehcdge005' -H 'cookie: deepfos_users=%7B%22color%22%3A%221%22%2C%22email%22%3A%22wei.wei%40proinnova.com.cn%22%2C%22nickName%22%3A%22Androiddown%22%2C%22token%22%3A%22FA8A64B5623403471566D1BAC673E19309D91D76056A2A889204BA1762B238B0%22%2C%22type%22%3A1%2C%22userId%22%3A%22c3c3e8fc-a6e2-443e-9091-75c19217c92c%22%2C%22username%22%3A%22jP5C29m6PW%22%7D; deepfos_token=FA8A64B5623403471566D1BAC673E19309D91D76056A2A889204BA1762B238B0' -H 'language: zh-cn' -H 'space: ehcdge' -H 'token: FA8A64B5623403471566D1BAC673E19309D91D76056A2A889204BA1762B238B0' -H 'user: c3c3e8fc-a6e2-443e-9091-75c19217c92c' -d '{"check_express": null, "dimensionMemberNames": "Account{Base1(#root, 0)}", "duplicate": true, "folderId": "DIR956996be86cb", "ignoreIllegalMember": true, "outFormat": null, "path": null, "resultString": "", "reverse_order": "0", "role": null, "roleFolderId": null, "rolegroup": null, "rsMapping": null, "rsName": null, "web": false}' https://alpha.deepfos.com/seepln-server/dimension-server1-0/dimension/query/select-dimension-member-by-name-function
Traceback (most recent call last):
  File "C:\Work\deepfos\_local_test\test_dim.py", line 8, in <module>
    dim.query("Base1(#root, 0)")
  File "C:\Work\deepfos\deepfos\element\dimension.py", line 387, in query
    return self.api.query.select_dimension_member_by_name_function(payload)
  File "C:\Work\deepfos\deepfos\api\base.py", line 340, in sync_call
    return handle_reponse(flag, obj, err, exception, model)
  File "C:\Work\deepfos\deepfos\api\base.py", line 308, in handle_reponse
    raise exc
deepfos.exceptions.APIResponseError: 维度表达式不正确

出现这类报错时,在报错的最后一行一般会有接口返回的错误提示, 如果设置了:

OPTION.api.dump_on_failure = True

在错误栈 Traceback (most recent call last): 的前一行,会打印一条包含本次请求信息的curl命令行。如果您判断是外部API的Bug,可以将curl命令行的内容复制并且发送给对应的开发人员。

在curl的前一行,会有包含本次请求完整返回和错误直接原因的简单说明。

解决方案 - 1

由于导致异常的原因多种多样,需要使用者结合报错的内容进行判断。 但是总体应该符合以下原则:

  1. 如果出现第5类情况: 返回的JSON无法依据Model定义反序列化,联系DeepFOS SDK开发者。

  2. 其余4类情况:

    1. 首先根据报错内容自我检查请求参数是否符合要求,

    2. 使用postman导入curl请求查看请求参数是否符合预期(可选,需要有一定开发经验)

      1. 不符合,联系DeepFOS SDK开发者

      2. 符合,进入下一步

    3. 联系接口开发者,提供curl命令行,协助排查Bug。

典型报错 - 2

Traceback (most recent call last):
  File "C:\Work\deepfos\_local_test\test1.py", line 11, in <module>
    dim = Dimension('tttt1')
  File "C:\Work\deepfos\deepfos\element\dimension.py", line 81, in __init__
    super().__init__(element_name, folder_id, path)
  File "C:\Work\deepfos\deepfos\element\base.py", line 47, in __init__
    ele_detail = self.init_element()
  File "C:\Work\deepfos\deepfos\element\base.py", line 53, in init_element
    ele_info = self.get_element_info()
  File "C:\Work\deepfos\deepfos\element\base.py", line 78, in get_element_info
    ele_list = api.elements.get_element_info_by_name(ele_name, ele_type)
  File "C:\Work\deepfos\deepfos\api\base.py", line 340, in sync_call
    return handle_reponse(flag, obj, err, exception, model)
  File "C:\Work\deepfos\deepfos\api\base.py", line 308, in handle_reponse
    raise exc
deepfos.exceptions.APIResponseError: [code: 401] ErrMsg from server: {"status":false,"data":null,"code":401,"message":"UNAUTHORIZED"}]

出现 code 401 或者 UNAUTHORIZED,通常由于cookie/token失效。

解决方案 - 2

更新 debug文件 中的para1参数。关于如何获取para1参数,请参考 这一节 内容。

Python内建异常及DeepFOS的Bug引发的异常

Python是一门强类型的动态类型语言,这种特性导致它比其他语言更容易抛出异常,例如 str 类型与 int 类型相加将导致 TypeError 等等,诸如此类的Python内建异常,需要多使用Python,积累开发经验,以便出现问题能够迅速定位。

值得一说的是,如果这种内建异常出现在DeepFOS的代码中,那么这可能是DeepFOS的一个Bug,欢迎您通过Issue向我们反馈。具体的流程可以参考 这一小节 内容。

DeepFOS主动抛出异常

在代码运行过程中,由于用户输入或者接口调用等获取的数据不符合预期,导致原有逻辑已经没有继续执行的必要,这时候通常主动抛出异常。 DeepFOS在抛出异常时会附带尽可能详尽的说明,以便您能够定位导致该异常的原因。

典型报错

Traceback (most recent call last):
  File "C:\Work\deepfos\_local_test\test_sml.py", line 6, in <module>
    sml = SmartList('project_approve_status2')
  File "C:\Work\deepfos\deepfos\element\smartlist.py", line 30, in __init__
    super().__init__(element_name, folder_id, path)
  File "C:\Work\deepfos\deepfos\element\base.py", line 47, in __init__
    ele_detail = self.init_element()
  File "C:\Work\deepfos\deepfos\element\base.py", line 53, in init_element
    ele_info = self.get_element_info()
  File "C:\Work\deepfos\deepfos\element\base.py", line 86, in get_element_info
    raise ElementNotFoundError(
deepfos.exceptions.ElementNotFoundError: element name: project_approve_status2, element type: SML.

解决方案

结合异常的名称和异常的详细内容,一般能够定位问题的原因。如果出现一些让你感到费解的错误或者某些报错缺乏友好提示,您也可以通过提Issue的方式反馈给我们。