Python: urllib.urlencode重复转义我的内容
...但是它并没有以同样的方式进行转义。
我正在尝试将gpg的ASCII输出上传到一个网站。所以到目前为止,我的代码只是查询数据库,显示我得到的数据,然后在为HTTP POST请求编码后再给我看:
cnx = connect()
sql = ("SELECT Data FROM SomeTable")
cursor = cnx.cursor()
cursor.execute(sql)
for (data) in cursor:
print "encoding : %s" % data
postdata = urllib.urlencode( { "payload" : data } )
print "encoded as %s" % postdata
...但是我得到的是:
encoding : -----BEGIN PGP MESSAGE-----
Version: GnuPG v1.4.12 (GNU/Linux)
.... etc...
encoded as payload=%28u%27-----BEGIN+PGP+MESSAGE-----%5CnVersion%3A+GnuPG+v1.4.12+... etc ...
需要注意的是,换行符没有像我预期的那样变成%0A。相反,它们以某种方式变成了"\n",然后反斜杠又被转义成了%5C,所以换行符变成了"%5Cn"。更奇怪的是,数据前面还加上了%28u%27,这变成了"(u'"。
奇怪的是,如果我只是做一个基本测试:
data = "1\n2"
print data
print urllib.urlencode( { "payload" : data } )
我得到了我预期的结果,换行符变成了%0A...
1
2
payload=1%0A2
所以,我的猜测是,从mysql查询返回的数据元素和我字面上的"1\n2"不是同一种字符串(可能是一个只有一个元素的字典...不知道),但我没有足够的Python知识去检查它。
有没有人知道这里发生了什么,以及我该如何解决?如果没有,是否有任何建议可以让我通过HTTP正确地POST这些数据?
1 个回答
假设 connect()
是某个符合 DB-API 2.0 标准的数据库接口的一个函数(比如内置的 sqlite3
,或者最常用的 mysql
接口),那么 for (data) in cursor:
其实是在遍历 Row
对象,而不是字符串。
当你打印出来的时候,实际上是打印 str(data)
(通过传递给 %s
格式)。如果你想要编码同样的内容,你需要对 str(data)
进行编码。
不过,更好的做法是一开始就把行当作行(只有一列)来处理,而不是依赖 str
来实现你想要的效果。
另外,如果你试图依靠元组解包来让 data
成为每行的第一个元素,那你就错了:
for (data) in cursor:
… 和下面这个是一样的:
for data in cursor:
如果你想要一个只有一个元素的 tuple
,你需要加个逗号:
for data, in cursor:
(如果你想的话,也可以加上括号,但加不加都没区别。)
具体来说,遍历游标会调用可选的 __iter__
方法,这个方法返回游标本身,然后循环调用 next
方法,这个方法的作用和调用 fetchone()
一样,直到结果集用完。而 fetchone
被描述为返回“一个单一的序列”,但它的类型并没有明确说明。在大多数实现中,这是一种特殊的行类型,比如 sqlite3.Row
,可以像访问 tuple
一样访问,但在打印成表格格式、按名称访问等方面有特殊的语义。