使用PyQt4 QNetworkAccessManager.post()方法时如何防止表单数据中的'+'被space替换

How to prevent '+' in form data being replaced by space when using PyQt4 QNetworkAccessManager.post() method

我的目标是 post 一些 http 表单数据,由 keyvalue 组成,使用 Python 2.7 和 PyQt4.QtNetwork.QNetworkAccessManager.post() 方法。

这本身不是问题。

问题是我的 value 是一个包含 '+' 的字符串,例如'a+b c',我需要它保持 '+',但是 post() 方法将其转换为 space,因此在原始请求中,我的示例值变为 'a b c'.

有谁知道是否有一些(最好是简单的)方法来防止这种情况发生?

下面提供了一个最小示例:

import sys
from PyQt4 import QtGui, QtCore, QtNetwork

def slot_close(reply_obj):
    print 'request sent by manager.post():\n'
    print reply_obj.readAll()
    reply_obj.deleteLater()
    app.quit()

app = QtGui.QApplication(sys.argv)

request = QtNetwork.QNetworkRequest(QtCore.QUrl('http://httpbin.org/post'))
request.setHeader(QtNetwork.QNetworkRequest.ContentTypeHeader,
    'application/x-www-form-urlencoded')

manager = QtNetwork.QNetworkAccessManager()
manager.finished.connect(slot_close)

form_data = QtCore.QUrl()
form_data.addQueryItem('my_key', 'a+b c')
urlencoded_form_data = form_data.encodedQuery()

# Show that the urlencoded_form_data still has a '+'
print 'urlencoded_form_data:\n{}\n'.format(urlencoded_form_data)

manager.post(request, urlencoded_form_data)

app.exec_()

请注意,例如requests.post() 方法确实实现了我的目标,启动起来更省力,但不幸的是我需要使用 QtNetwork。

虽然我一直在寻找更优雅的东西,但一个可行的选择是用其转义版本替换 urlencoded 字符串中的加号。对于上面的示例,那将是:

urlencoded_form_data.replace('+', '%2B')

一种替代方法是像这样对查询项进行显式编码:

formdata.addEncodedQueryItem('my_key', QUrl.toPercentEncoding('a+b c'))

请注意,严格来说,如果密钥可以包含非 ASCII 字符或保留字符,则第一个参数应以相同的方式编码。 toPercentEncoding function gives you complete control over exactly which characters are encoded, and by default, it will do the right thing. But also note that addEncodedQueryItem 本身不做任何检查,因此由调用者确保两个参数都正确编码。