Python: urllib.urlencode重复转义我的内容

0 投票
1 回答
792 浏览
提问于 2025-04-17 17:13

...但是它并没有以同样的方式进行转义。

我正在尝试将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 个回答

0

假设 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 一样访问,但在打印成表格格式、按名称访问等方面有特殊的语义。

撰写回答