如何调试requests库?

5
我正在尝试从使用os.system()发出curl命令的Python脚本转为使用requests。我曾想过使用pycurl,但这个问题让我打消了念头。问题是我从服务器得到了一个错误返回,我可以在使用r.text时看到(来自这个答案),但我需要更多信息。有更好的方法来调试发生的情况吗?

如果值得一提的是,我认为问题围绕着将我的 --data 标志从curl/pycurl转换为requests。之前,我已经创建了一个向 --data 传递参数的字典。我猜其中一个不是有效的,但如何获取更多信息以确保呢?

示例:

headers2 = {"Accept":"*/*", \
"Content-Type":"application/x-www-form-urlencoded", \
"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36", \
"Origin":"https://somedomain.com", \
"X-Requested-With":"XMLHttpRequest", \
"Connection":"keep-alive", \
"Accept-Language":"en-US,en;q=0.8", \
"Referer":"https://somedomain.com/release_cr_new.html?releaseid=%s&v=2&m=a&prev_release_id=%s" % (current_release_id, previous_release_id), \
"Host":"somedomain.com", \
"Accept-Encoding":"gzip,deflate,sdch", \
"Cookie":'cookie_val'}

for bug_id in ids:
  print bug_id
  data = {'dump_json':'1','releaseid':current_release_id, 'v':'2','m':'a','prev_release_id': previous_release_id,'bug_ids': bug_id, 'set_cols':'sqa_status&sqa_updates%5B0%5D%5Bbugid%5D=' + bug_id + '&sqa_updates%5B0%5D%5Bsqa_status%5D=6'}
  print 'current_release_id' , data['releaseid']
  print 'previous_release_id', data['prev_release_id']
  r = requests.post(post_url, data=json.dumps(data), headers=headers2)
  print r.text

我得到的输出是一个非常普通的HTML消息,当我以错误的方式查询服务器时,我以前见过这个消息。所以至少我知道我正在访问正确的服务器。
我并不真正期望任何输出。这只是向服务器发送POST请求并更新数据库中的字段。

你能否提供一个示例(包括输入、期望输出和实际输出)?你可以指向 http://httpbin.org/ (如果你不想将数据发送到那里,你可以在 github 上进行 fork)。这可能有助于你调试差异。 - Wayne Werner
我尝试用一个例子来更新它。起初我有些犹豫,因为我以前常常会忘记掩盖一些东西。 - Ramy
我尝试了一下编码 - 将其完全删除,但结果没有改变。 - Ramy
2个回答

5

HTTP响应的解剖

示例(加载此页面)

HTTP/1.1 200 OK
Cache-Control: public, max-age=60
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Expires: Fri, 27 Sep 2013 19:22:41 GMT
Last-Modified: Fri, 27 Sep 2013 19:21:41 GMT
Vary: *
X-Frame-Options: SAMEORIGIN
Date: Fri, 27 Sep 2013 19:21:41 GMT
Content-Length: 12706

<!DOCTYPE html>
<html>
... truncated rest of body ...
  1. 第一行是状态行,由状态码状态文本组成。
  2. 头部是键值对。头部以空的新行结束。空行表示没有更多头部,接下来是有效载荷/正文的开始。
  3. 正文占据了消息的其余部分。

以下是如何提取这3个部分的说明:

状态行

使用以下内容获取服务器返回的状态行

>>> bad_r = requests.get('http://httpbin.org/status/404')
>>> bad_r.status_code
404

>>> bad_r.raise_for_status()
Traceback (most recent call last):
  File "requests/models.py", line 832, in raise_for_status
    raise http_error
requests.exceptions.HTTPError: 404 Client Error

(source)

Headers:

r = requests.get('http://en.wikipedia.org/wiki/Monty_Python')
# response headers: 
r.headers
# request headers:
r.request.headers

正文

使用r.text

POST请求编码

发送到服务器的请求的“内容类型”应与实际发送的内容类型匹配。在您的情况下,您正在发送json数据,但告诉服务器您正在发送表单数据(如果未指定,默认为表单数据)。

从您上面显示的标题中:

"Content-Type":"application/x-www-form-urlencoded",

但是,您的request.post调用设置了data=json.dumps(data),这是JSON数据。标题应如下所示:

"Content-type": "application/json",


太好了!所以,我盲目地复制了 json.dumps 这一部分。form-urlencoded 是正确的编码类型。我将其更改为 data=data,现在响应似乎更准确了,但它并没有完全做我期望的事情。我会接受这个答案并继续挖掘。 - Ramy

0

request 对象返回的值包含了请求信息,位于 .request 下。

例如:

r = requests.request("POST", url, ...)

print("Request headers:", r.request.headers)
print("Request body:", r.request.body)

print("Response status code:", r.status_code)
print("Response text:", r.text.encode('utf8'))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接