python - zabbix API json 请求与 python urllib.request

标签 python json urllib zabbix

我正在开发我的 python 项目,并从 python2.6 迁移到 python 3.6。所以我不得不用 urllib.request 替换 urllib2 (以及 .error 和 .parse )。

但是我遇到了一个无法解决的问题,这就是......

我想发送一个用 JSON 编写的请求,如下所示:

import json
import urllib2

data= json.dumps({
        "jsonrpc":"2.0",
        "method":"user.login",
        "params":{
             "user":"guest",
             "password":"password"
        }
        "id":1,
        "auth":None
     })

使用 urllib2 我没有遇到任何问题,我只需使用以下命令创建请求:

req=urllib2.Request("http://myurl/zabbix/api_jsonrpc.php",data,{'Content-type':'application/json})

发送:

response=urllib2.urlopen(req)

这很好,但现在使用 urllib.request,我遇到了库引发的许多错误。检查我做了什么(请求与“数据”中的请求相同):

import json
import urllib.request

data= json.dumps({
        "jsonrpc":"2.0",
        "method":"user.login",
        "params":{
             "user":"guest",
             "password":"password"
        }
        "id":1,
        "auth":None
     })
req = urllib.request.Request("http://myurl/zabbix/api_jsonrpc.php",data,{'Content-type':'application/json})

response = urllib.request.urlopen(req) 

我收到此错误:

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/tmp/Python-3.6.1/Lib/urllib/request.py", line 223, in urlopen
    return opener.open(url, data, timeout)
  File "/tmp/Python-3.6.1/Lib/urllib/request.py", line 524, in open
    req = meth(req)
  File "/tmp/Python-3.6.1/Lib/urllib/request.py", line 1248, in do_request_
raise TypeError(msg)
TypeError: POST data should be bytes, an iterable of bytes, or a file object. It cannot be of type str.

所以我询问了这一点,得知我必须使用函数 urllib.parse.urlencode() 将我的请求转换为字节,所以我尝试在我的请求上使用它:

import urllib.parse

dataEnc=urllib.parse.urlencode(data)

发生另一个错误:

Traceback (most recent call last):
  File "/tmp/Python-3.6.1/Lib/urllib/parse.py", line 842, in urlencode
    raise TypeError
TypeError

During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/tmp/Python-3.6.1/Lib/urllib/parse.py", line 850, in urlencode
    "or mapping object").with_traceback(tb)
  File "/tmp/Python-3.6.1/Lib/urllib/parse.py", line 842, in urlencode
    raise TypeError
TypeError: not a valid non-string sequence or mapping object

我意识到 json.dumps(data) 只是将我的数组/字典转换为字符串,这对于 urllib.parse.urlencode 函数无效,所以我从数据中退休了 json.dumps 并执行了以下操作:

import json
import urllib.request
import urllib.parse

data= {
        "jsonrpc":"2.0",
        "method":"user.login",
        "params":{
             "user":"guest",
             "password":"password"
         }
         "id":1,
         "auth":None
      }

dataEnc=urllib.parse.urlencode(data) #this one worked then

req=urllib.request.Request("http://myurl/zabbix/api_jsonrpc.php",data,{'Content-type':'application/json})

response = urllib.request.urlopen(req) #and this one too, but it was too beautiful

然后我查看了回复并得到了这个:

b'{"jsonrpc":"2.0",
   "error":{
         "code":-32700,
         "message":"Parse error",
         "data":"Invalid JSON. An error occurred on the server while parsing the JSON text."}
    ,"id":1}

我猜这是因为 JSON 消息不是 json.dumped!

总有一个因素阻止我正确执行请求,

所以我完全坚持下去,如果你们中有人有想法或替代方案,我会很高兴。

致以诚挚的问候

Gozu09

最佳答案

事实上,您只需将 json 数据作为字节序列传递,如下所示:

data= {
    "jsonrpc":"2.0",
    "method":"user.login",
    "params":{
        "user":"guest",
        "password":"password"
    }
    "id":1,
    "auth":None
}

req = urllib.request.Request(
    "http://myurl/zabbix/api_jsonrpc.php",
    data=json.dumps(data).encode(),  # Encode a string to a bytes sequence
    headers={'Content-type':'application/json}
)

POST data should be bytes, an iterable of bytes, or a file object. It cannot be of type str

此错误意味着 data 参数应该是字节的可迭代对象。

st = "This is a string"
by = b"This is an iterable of bytes"
by2 = st.encode() # Convert my string to a bytes sequence
st2 = by.decode() # Convert my byte sequence into an UTF-8 string

json.dumps() 返回一个字符串,因此您必须调用 json.dumps().encode() 将其转换为字节数组。

顺便说一句,当您想要转换将作为 url 参数传递的字符串时,请使用 urlencode(:将空格字符转换为“%20”)。该方法的输出是字符串,而不是字节数组

关于python - zabbix API json 请求与 python urllib.request,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44160561/

相关文章:

python - 替换/删除字符串中的字符

python - 如何在 python 中使用 openpyxl 提取列中的最后一个单元格

python - Python 数据库 API 中是否指定了连接对象的 __enter__ 和 __exit__ 行为?

json - JSONiq 和 XQuery 3.1 之间有什么区别?

javascript - 使用 D3PLUS 在 TreeMap 中使用 json 递归的问题

python - 使用 urlopen 获取 FTP 服务器上文件的最后修改日期不起作用

python - 由于 SSLError,urllib.request.open 无法打开 URL

python - 如何完成 django-userena 和 Social Auth 的集成

python 请求

python - BeautifulSoup - urllib.error.HTTPError : HTTP Error 403: Forbidden