尝试通过函数参数将正文发送到 API 时出现 KeyError

Posted

技术标签:

【中文标题】尝试通过函数参数将正文发送到 API 时出现 KeyError【英文标题】:KeyError when trying to send body to API via function parameter 【发布时间】:2020-03-04 12:07:45 【问题描述】:

尝试通过 python 函数向 API 发送 POST 请求,但我无法遍历字符串列表并将字符串传递给函数。

在 Postman 中成功测试了这一点(请求以 Postman 中所示的“原始 Body”形式向 API 发送一个字符串)。将代码从 Postman 复制到 Python,并验证它也可以工作。问题是,如果我将静态字符串更改为函数的参数,我会得到一个 KeyError,但是如果我只是将参数(它是一个值,而不是键)替换为一个字符串,那么 keyerror 就会消失。

这行得通...

payload = "\"ids\":[\"cb5f9a97c0e749ab67409e78b4fcb11d\"]" works

但是这些都不起作用(注意右边的错误代码);尤其是前两个和上面一模一样……

payload = "\"ids\":[\"0\"]".format(id) #gives KeyError: '"ids"'
payload = "\"ids\":[0]".format(id) #gives KeyError: '"ids"'
payload = "'ids':'[0]'".format(id) #gives KeyError: "'ids'"
payload = "ids:[\"0\"]".format(id) #gives KeyError: 'ids'

我还尝试修改键/值对中的键 ('ids'),导致出现 NameErrors。由于这偏离了上面已知的工作示例,我认为以下尝试不值得继续尝试......

payload = ids:"[0]".format(id) #gives NameError: name 'ids' is not defined
payload = ids:"0".format(id) #gives NameError: name 'ids' is not defined
payload = ids:id #gives NameError: name 'ids' is not defined

我什至验证了从列表中生成的字符串实际上是一个字符串。

完整(相关)代码如下:

def cs_delete(id):
    print(id)
    url = "https://api.crowdstrike.com/devices/entities/devices-actions/v2"
    querystring = "action_name":"hide_host"
    payload = "'ids':['0']".format(id)
    headers = 
    'Content-Type': "application/json",
    'Authorization': "Bearer " + cs_auth,
    'Accept': "*/*",
    'Cache-Control': "no-cache",
    'Host': "api.crowdstrike.com",
    'Accept-Encoding': "gzip, deflate",
    'Content-Length': "83",
    'Connection': "keep-alive",
    'cache-control': "no-cache"
    
    response = requests.request("POST", url, data=payload, headers=headers, params=querystring)
    print(response.text)

for host in dfList:
    print(host)
    cs_delete(host)

为了完整起见,dfList 显示为:

['2a9cf64988e6464f7d2ba7f305a612f3', '5ba4654e1dbe418f7b6361582e3d8f47', '7c6fc20572c241f664813f48bb36c340', 'ccbaf1ebe52042fc6b8269bf86732676']

【问题讨论】:

为什么不json.dumps('ids': [id]) 基本上是这样做的,但使用请求的功能,因为它更容易......即我使用 json=payload 而不是 data=payload "不用自己对dict进行编码,也可以直接使用json参数传递(2.4.2版本新增),它会自动编码"。请参阅requests.kennethreitz.org/en/master/user/quickstart/… 了解更多信息。 那么为什么要自己对它进行字符串化呢?! json='ids': [id]. 【参考方案1】:

将外部大括号加倍以对其进行转义,否则format() 将期望输入值应用于外部大括号而不是0

>>> id = 'cb5f9a97c0e749ab67409e78b4fcb11d'
>>> "'ids':[0]".format(id)
"'ids':[cb5f9a97c0e749ab67409e78b4fcb11d]"

【讨论】:

清除了 keyerror 问题,但现在我得到了一个 400 的消息:""提供的数据与预期的 'Action Parameter' 格式不匹配"',我没有通过使用 "\" ids\":[\"cb5f9a97c0e749ab67409e78b4fcb11d\"]" (或任何其他静态字符串) 工作。需要使用 json= 而不是 data= 因为 API 需要 json。最终使用了 payload = "ids":[id]。谢谢马特!

以上是关于尝试通过函数参数将正文发送到 API 时出现 KeyError的主要内容,如果未能解决你的问题,请参考以下文章

Python Post 请求 - 通过 Outlook API 发送文件时出现 415 错误

通过 Python API 客户端将经过验证的查询发送到 BigQuery 时出现语法错误

尝试使用 twilio Api phpSDK 发送消息时出现致命错误

从画布正确获取信息并通过带有 node-fetch 的 webhook 将信息发送到 discord 时出现问题

使用 Gmail API 发送大型附件时出现错误 10053

正文未通过 Azure API 管理发送