【问题标题】:Include unicode chars in python3 dict在 python3 dict 中包含 unicode 字符
【发布时间】:2021-04-30 02:49:15
【问题描述】:

我正在尝试将带有标签的字典发送到 check_mk web-api - 但是 web-api 使用 python2 - 并且开发人员坚持要验证标签是 Unicode。

我在 p3 中的示例字典:

"": [
    {
        "condition": {
            "service_description": [
                {
                    "$regex": "Callcentre Queue: OTU"
                }
            ]
        },
        "value": {
            u"max_check_attempts": u"3"
        },
        "options": {
            "description": "Label - max_check_attempts\nService - Callcentre Queue: OTU"
        }
    }]

但发送后,我收到label max_check_attempts must be unicode type 错误。

Traceback (most recent call last):
  File "./cmk_import.py", line 415, in <module>
    process_service_rulelist()
  File "./cmk_import.py", line 309, in process_service_rulelist
    api().set_ruleset('service_label_rules', total_lbl_ruleset)
  File "/usr/local/lib/python3.6/dist-packages/check_mk_web_api/__init__.py", line 724, in set_ruleset
    return self.make_request('set_ruleset', data=data, query_params={'request_format': 'python'})
  File "/usr/local/lib/python3.6/dist-packages/check_mk_web_api/__init__.py", line 164, in make_request
    raise CheckMkWebApiException(result)
check_mk_web_api.exception.CheckMkWebApiException: Check_MK exception: ERROR: The label ID 'max_check_attempts' is of type <type 'str'>, but should be unicode. Affected Rule {'value': {'max_check_attempts': '3'}, 'condition': {'service_description': [{'$regex': 'Callcentre Queue: OTU'}]}, 'options': {'description': 'Label - max_check_attempts\nService - Callcentre Queue: OTU'}}

错误来自 check_mk web-api 发出的 checkMK 本身。由于监听代理是 Python2 - 它正在尝试将 type() 验证为 unicode

我知道 P3 已将 unicode 合并到 str 中 - 但想知道是否有一种方法可以覆盖和保留 dict unicode 字符而不重写 python2 中受影响的部分。

Web 请求由这个库处理 - https://github.com/brennerm/check-mk-web-api

request = urllib.request(self._build_request_path(query_params),WebApi._build_request_data(data, request_format))

其中的内容是: Arg1:

http://localhost/preprod/check_mk/webapi.py?effective_attributes=0&action=get_all_hosts&_username=automation&_secret=foobar

还有片段:

{%27condition%27: {%27service_description%27: [
{%27%24regex%27: %27VPN: Premier Ping - 1.1.1.1%27}

]}, %27value%27:
{%27check_interval%27: %275%27, %27max_check_attempts%27: %273%27, %27retry_interval%27: %271%27, %27check_period%27: %2724x7%27, %27notification_period%27: %2724x7%27, %27notification_interval%27: %27120%27, %27notifications_enabled%27: %271%27, %27active_checks_enabled%27: %271%27, %27check_freshness%27: %270%27, %27event_handler_enabled%27: %271%27, %27flap_detection_enabled%27: %271%27, %27is_volatile%27: %270%27, %27obsess_over_service%27: %271%27, %27passive_checks_enabled%27: %271%27, %27process_perf_data%27: %271%27, %27retain_nonstatus_information%27: %271%27, %27retain_status_information%27: %271%27}
, %27options%27: {%27description%27: %27Labels for Service - VPN: Premier Ping - 1.1.1.1%27}}

【问题讨论】:

  • Python 3 字符串已经是 Unicode。你不需要做任何特别的事情。甚至 a 也是一个 Unicode 字符。问题在于您如何向该 Web API 发出请求。您是否在请求中使用了错误的content-type
  • P3 has incorporated unicode into str 不,这根本不是发生的事情。 Python 3 字符串 Unicode,句号。没有什么可以验证或验证的。 Unicode 不是某种转义序列,它是 all 字符转换为字节的方式。如果您对 HTTP 请求有编码问题,请发布您的 HTTP 代码
  • 道歉我已经编辑了 - “max_check_attempts”之前的“u”字符,它的值是 web-api 所期望的。我对 curl 做了同样的事情 - web-api 接受 python2 格式的 'u' 前缀,但如果它不存在则不接受。
  • @PanagiotisKanavos - 它似乎与我发送到 web-api 的特定字符串有关。您认为可能是实际的 Web 请求需要将其从 python3 渲染为 python2 兼容格式?
  • 所以 API 期望您通过 HTTP 将字符串 {u"foo": u"bar"} 发送给它?这意味着它可能仅仅依靠str({'foo': 'bar'}) 并发送它?这仅适用于 Python 2,因为在 Python 3 中您不会从中获得 u 前缀? — 那是一个糟糕的 API,期待 特定语言,甚至更特定于特定语言的过时版本,输入格式......

标签: python python-3.x check-mk


【解决方案1】:

API 客户端以它所谓的“python”格式发送数据,这基本上是一个调用了str() 的字典。目的是服务器将在此字典字符串上调用ast.literal_eval()。客户端对响应的正文执行相同的操作。将其转换回 Python 字典。

在整个 API 中,有些地方确实支持 JSON 以进行请求/响应处理,这可以在某些函数的查询参数中进行设置。不幸的是,对于此处失败的特定请求 (set_ruleset),JSON 不是一个选项。

服务器未能处理此请求的原因尚不清楚。我尝试取消引用消息正文并在 Python 2 中通过 literal_eval() 运行它,它似乎有效。

我注意到的一件事是请求字典 "Label - max_check_attempts\nService - Callcentre Queue: OTU" 中嵌入的换行符。这可能是服务器在提到“标签 ID 'max_check_attempts'”时所抱怨的。

进一步的问题跟踪需要查看服务器日志,可能还需要查看代码以了解那里发生了什么。

【讨论】:

  • 在我看来,服务器可能是 literal_evaling 它在 Python 2 中,并且无论输入是否包含 u,您显然会得到不同的数据类型与否,然后它会验证 那个 eval 的数据类型。
  • @deceze 也许,但我在 Python 2 中尝试了 literal_eval 在我认为它发送的请求正文上,它通过了。也许是不同版本的 Python 2,或者我对服务器所做的事情的猜测是错误的。 OP 没有说,但我认为其他请求正在成功,正如我在回答中提到的那样,有些可以/确实使用 JSON,而有些则不能。嵌入的换行符仍有可能是服务器不喜欢的,我可以想象它会对此进行验证。
  • @mhawke 谢谢 - 我已经删除了嵌入的换行符,但请求仍然失败。 CheckMkWebApiException: Check_MK exception: ERROR: The label ID 'check_period' is of type &lt;type 'str'&gt;, but should be unicode. Affected Rule {'value': {'check_period': '24x7', 'notification_interval': '120', 'notification_period': '24x7', 'retry_interval': '1', 'check_interval': '5', 'max_check_attempts': '2'}, 'condition': {'service_description': [{'$regex': 'Router: Uptime'}]}, 'options': {'description': 'Labels for Service - '}}
  • 有趣的是,我确实测试了 api().get_ruleset('service_label_rules') 并将其发送回完全相同,但失败了。打印请求时,返回包含u,但是在被python3处理后,u被剥离。check_mk_web_api.exception。
  • 如果您运行的是 Python 3.6,它如何包含 u 前缀?您的意思是“打印响应时”吗?
猜你喜欢
  • 2020-05-06
  • 2011-01-28
  • 2020-12-19
  • 2021-11-23
  • 2019-01-29
  • 1970-01-01
  • 1970-01-01
  • 2015-06-09
  • 2016-06-12
相关资源
最近更新 更多