Python 3 中如何解决字典对字符串进行转义

2020-01-21 11:17:04 +08:00
 euzen
str = "源代码"
bytes = str.encode('utf-8')
str2 = bytes.decode('iso-8859-1')
dict = {"key": str2}
print(bytes)
print(str2)
print(dict)

运行结果:
b'\xe6\xba\x90\xe4\xbb\xa3\xe7\xa0\x81'
源代码
{'key': 'æº\x90代ç\xa0\x81'}

赋值给字典后,会对小于\xa1 的字节进行转义,当使用 request.post 进行文件上传时,files 参数中涉及中文文件名就无法正确提交,有什么办法可以解决?
6995 次点击
所在节点    Python
38 条回复
xuboying
2020-01-21 13:32:04 +08:00
æºä»£ç 
{'key': 'æº\x90代ç\xa0\x81'}
这两个内容有啥区别。。。

这是你的 terminal 渲染的结果,如果你的 terminal 的 locale,( windows 下是 chcp 值) 不同,会用其他的字体渲染出其他的结果,就好比一个苹果放在中国会写成苹果,放在美国会写成 apple,本质是完全一样的东西。

要担心的是 utf8 到 iso8859 的互转会不会丢失信息,毕竟你的服务器要按照 8865 的结果转回去。不知道是不是可逆的
also24
2020-01-21 13:34:41 +08:00
刚睡醒,仔细看了下应该不是同一个问题,我再看看楼主到底想干啥…
also24
2020-01-21 13:48:59 +08:00
认真的看了一下,楼主你这个问题没有描述清楚哈:

> 服务器就是接受 iso-8859-1 编码
这个是根据什么判定的?怎么测试出来的?

> 必须提交'\xe6\xba\x90\xe4\xbb\xa3\xe7\xa0\x81' 才可以
是说这样提交就可以正常使用?这个是 utf-8,不是 iso-8859-1 啊,和上一条的结论似乎不一样?

> 使用 request.post
指的是 requests.post 嘛?(少了 s )
如果是的话,我现在怎么觉得和我一开始认为的是同一个问题了呢……
如果是这样的话,那还是看一下 urllib3 的版本号


BTW:
赞同 @xuboying 关于最开始那几种展示无区别的看法。

BBTW:
我感觉楼主还没有把整个问题的完整情况搞清楚。
建议使用抓包软件抓一下 requests 发出的原始请求,确认编码情况。
zappos
2020-01-21 14:00:14 +08:00
也就是说 requests 库不会对 multipart 格式的中文自动编码是吧。我忘了 multipart 是怎么搞得了,你可以随便传个文件看一看。

还有就是不要用不同的编码 encode 和 decode。
CRVV
2020-01-21 14:23:52 +08:00
显然是 XY problem,还没把 Y 问题说清楚

原本的问题是服务器不认 python 传过去的汉字,然后楼主拿 encode decode 和 iso-8859-1 折腾了一下就成功了,以为是服务器只支持 iso-8859-1。
但实际上显然不是这么回事,如果服务器只支持 iso-8859-1,那就不可能成功地把汉字传上去。
但是楼主又没说到底是怎么把字符串传给服务器的,如果是下面这样,说明服务器不支持 \u4e2d 这种编码 unicode 的方法。json.dumps 有一些带默认值的参数,改一改可能服务器就支持了。

>>> json.dumps('中'.encode('utf-8').decode('iso-8859-1'))
'"\\u00e4\\u00b8\\u00ad"'
>>> json.dumps('中')
'"\\u4e2d"'

至于后面的文件读不出来
'源代码' 这个字符串用 utf-8 编码过后的结果,再用 iso-8859-1 reinterpret 出来,就不是原来的字符串了,新的字符串是 'æº\x90代ç\xa0\x81',如果你要读的文件是 '源代码',那当然读不到

.encode('utf-8').decode('iso-8859-1') 是相当于 float x = 3.14159; int* y = (int*)&x; 这样的操作,正常情况下不会用到的。
euzen
2020-01-21 16:36:50 +08:00
@also24 urllib3 1.23.2
我觉得也是你说的这个问题。
euzen
2020-01-21 16:52:24 +08:00
@also24 自己另外搭了个测试页面来验证,有中文名字的话,服务器端接收完全是空的。
euzen
2020-01-21 16:55:15 +08:00
@xuboying 是的,确认跟这个没关系,是我搞错方向了。
euzen
2020-01-21 16:56:41 +08:00
@CRVV 的确是开始没搞清楚,跟编码没关系。
also24
2020-01-21 16:58:40 +08:00
@euzen #27
那和 urllib3 这个有关的可能性就非常大了……

可以直接抓包把原始的请求内容拿出来看一下,或者在服务端打印一下所有字段的信息。

懒得追查的话也可以先把 urllib3 升级到 1.25 版本以上看看问题会不会自动消失。


你这个问题真的是搞了个超大的 X-Y Problem 出来……
euzen
2020-01-21 17:46:30 +08:00
@also24 升级到 1.25.7,可以在测试服务器上看到文件名有数据了,虽然编码还是不对,但距离解决已不远,谢谢你的解答。前期纠结编码,主要是服务器不能管理,无法验证。
also24
2020-01-21 17:57:37 +08:00
@euzen #31

那就用我一直建议的抓包的方式,你 requests 配置一下 Proxies,然后用 Charles 之类的工具看一下发出去的原始请求的具体格式,避免一直黑箱状态下摸瞎改代码。

https://2.python-requests.org/en/master/user/advanced/#proxies
luoleng
2020-01-21 21:39:28 +08:00
想要啥效果?{'key': b'\xe6\xba\x90\xe4\xbb\xa3\xe7\xa0\x81'}还是{'key': '\xe6\xba\x90\xe4\xbb\xa3\xe7\xa0\x81'}
euzen
2020-01-21 21:49:14 +08:00
@luoleng 原方向是需要后者的结果,但现在经 @also24 指点,发现跟字典无关,是 urllib3 低版本的问题。同时我关于字典会转义的指控也是错的,并没有转义,只是__repr__和__str__的区别。
euzen
2020-01-21 22:07:24 +08:00
@also24 真是长见识了,requests 还可以使用 proxies,明天配合 burp 尝试一下。
also24
2020-01-21 22:41:51 +08:00
@euzen #35
哈哈哈哈,再多嘴两句哈,我觉得你查找问题的思路需要改进一下。

不太建议上来就靠着直觉猜,应该先尽可能收集能收集到的信息(日志,原始请求等)。

先搞清楚问题的全貌,才能对症下药,不然就很容易搞出这种 X-Y Problem,白费大量精力。
yhyh
2020-01-22 14:01:31 +08:00
你这个问题 感觉有固定的方案可以解决,我奇葩的是 字典转 json, 而字典的值 有双引号
哭了
euzen
2020-01-23 09:02:59 +08:00
@CRVV 关于编码的问题,摸索了一天,再细读你的回复,利益不少。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/639618

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX