2017-05-24 135 views
1

我正在处理我的python项目,并且我从python2.6迁移到python 3.6。所以我不得不用urllib.request(和.error和.parse)替换urllib2。zabbix API使用python的json请求urllib.request

但我面临的一个问题,我解决不了,这里是......

我想给写在JSON象下面这样的请求:

import json 
import urllib2 

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

与我的urllib2面对没问题,我不得不创建一个请求:

response=urllib2.urlopen(req) 
012:

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

与发送

这很好,但现在与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(数据)只是将我的数组/字典转换为一个字符串,这对urllib.parse.urlencode函数无效,soooooo我从数据中取消了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.dumped JSON的消息!

总有一个元素正确地做请求阻挡我,

所以我完全坚持了下来,如果有的话你们有一个想法或替代我会很高兴。

问候

Gozu09

回答

1

其实你只需要通过你的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数据应该是字节,一个迭代字节或文件对象。它不能是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()将其转换为一个字节数组。

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

+1

它的工作,非常感谢 – Gozu09