接口测试 关于在 python 中使用 requests 框架传入中文参数问题

testblue · 2017年03月16日 · 最后由 Botree_chen 回复于 2018年09月14日 · 3876 次阅读
def requestsMethodForPost(param):
url = upGradeUrl + '?'
request = requests.post(url, data=param)
response = request.text
print response
respDic = json.loads(response)
return respDic

大神们,我用python做接口自动化测试,遇到这么一个问题,在用requests中post请求的时候,参数中会带有中文,然后我就直接把中文传进去了:

params = {
'from':'internal',
'gps_type':'baidu',
'lat':'40.018597',
'lng':'116.476326',
'mac':'b4:30:52:5e:6d:61',
'model':'HUAWEI-HUAWEI C8817E',
'name':'先生',
'order_id':self.order_id,
'os':'HUAWEI19,4.4.4',
'phone':'13000000090',
}

然后,我就post出这个请求,但是在控制台,这个中文被直接自动转换为'\xe5\x85\x88\xe7\x94\x9f',导致这个传参一直是错误的,服务端会去校验你传入的值是否为正确编码格式,而python默认不会直接传入中文数据,这个有人遇到过吗

最佳回复

假如服务端是接受GBK编码,对于python 3来说,中文POST参数应这样写
```python 3
#requests (2.18.4)

'name': '先生'.encode('GBK'), #生成 bytes类型,而不要用str。因为str会默认由utf-8 编码。如果服务端也用UTF-8解码中文,应该不会有问题。

以下是models.py原文 site-packages\requests 目录下

```python
def _encode_params(data):
"""Encode parameters in a piece of data.

Will successfully encode parameters when passed as a dict or a list of
2-tuples. Order is retained if data is a list of 2-tuples but arbitrary
if parameters are supplied as a dict.
"""


if isinstance(data, (str, bytes)):
return data
elif hasattr(data, 'read'):
return data
elif hasattr(data, '__iter__'):
result = []
for k, vs in to_key_val_list(data):
if isinstance(vs, basestring) or not hasattr(vs, '__iter__'):
vs = [vs]
for v in vs:
if v is not None:
result.append(
(k.encode('utf-8') if isinstance(k, str) else k,
v.encode('utf-8') if isinstance(v, str) else v))
return urlencode(result, doseq=True)
else:
return data


关键位置在于对k,v的处理,所以假如提供的是,b'\xcf\xc8\xc9\xfa' 这样的数据,会原样传给服务器。
但是假如服务器也是UTF-8处理中文,则完全不用这样。这样服务器接收到的name值就是'先生'.encode('utf-8') .也许是b'\xe5\x85\x88\xe7\x94\x9f'。
然后它还要经过urldecode处理以后,再反向解析成中文字符串。就是你看到的这个样子'\xe5\x85\x88\xe7\x94\x9f' 这就是name参数的内存格式。
假如控制台只能接受和显示GB2312、 要对这个字符串做 utf-8 转GBK的处理才能显示出来了。

这是两个关于汉字编码的地址可做参考
http://www.cnblogs.com/ttltry-air/p/3325543.html
https://www.zhihu.com/question/26921730

共收到 16 条回复 时间 点赞

感觉这个跟post请求没关系,看看有没有在文件开头加上#coding=utf-8

—— 来自TesterHome官方 安卓客户端

limit 回复

还真是加了的,# -- coding: utf8 --
但是还是不太行啊,他关键会自己转换

  • 在中文前面加个
'name':u'先生',

试一下。

可以使用fiddler 抓包下你post 的数据,查看下是否正确。Inspectors→webForms→bodydata

编码编码,格式转换,你先问一下,接口接受的默认编码是啥子,然后转换你的参数后在传递

我觉得接口测试中,你还要考虑加解密的封装,正则匹配,特别是断言的正则匹配

xie_0723 回复

这个我还真试过了,结果是unicode类型字符串,还是不能通过接口测试

json.dumps( params, ensure_ascii = False, separators = (',', ':') )

lingcizhisheng 回复

对了,多问您一句,您平时断言怎么写的,比如正常接口返回值code=0,然后当我任意传递参数不正确的时候返回code值为1,那我断言就写一个正确的传参用例和几个错误的传参用例,当错误的时候,self.assertEqual(respDic['code'],1),符合预期用例通过,但是,明显的我服务器这时候是有问题的啊,他返回非零就是有问题的但是我用例跑通过了,这如何能抓到服务的错误,感觉很矛盾啊

换python 3试试

daqiao 回复

python3网上说是可以的,但是如果换的话感觉有些格式的编写就需要修改,不是太方便,当然也是可以解决这个问题的,辛苦

lingcizhisheng 回复

我试了下目前情况是这样的,接口测试用post请求的时候,当我直接打印param中的信息的时候,中文就直接被转为16进制了,当我param['name']的时候,就会打印出中文,很纳闷啊

把中文先编码,然后再组装到json里试试

假如服务端是接受GBK编码,对于python 3来说,中文POST参数应这样写
```python 3
#requests (2.18.4)

'name': '先生'.encode('GBK'), #生成 bytes类型,而不要用str。因为str会默认由utf-8 编码。如果服务端也用UTF-8解码中文,应该不会有问题。

以下是models.py原文 site-packages\requests 目录下

```python
def _encode_params(data):
"""Encode parameters in a piece of data.

Will successfully encode parameters when passed as a dict or a list of
2-tuples. Order is retained if data is a list of 2-tuples but arbitrary
if parameters are supplied as a dict.
"""


if isinstance(data, (str, bytes)):
return data
elif hasattr(data, 'read'):
return data
elif hasattr(data, '__iter__'):
result = []
for k, vs in to_key_val_list(data):
if isinstance(vs, basestring) or not hasattr(vs, '__iter__'):
vs = [vs]
for v in vs:
if v is not None:
result.append(
(k.encode('utf-8') if isinstance(k, str) else k,
v.encode('utf-8') if isinstance(v, str) else v))
return urlencode(result, doseq=True)
else:
return data


关键位置在于对k,v的处理,所以假如提供的是,b'\xcf\xc8\xc9\xfa' 这样的数据,会原样传给服务器。
但是假如服务器也是UTF-8处理中文,则完全不用这样。这样服务器接收到的name值就是'先生'.encode('utf-8') .也许是b'\xe5\x85\x88\xe7\x94\x9f'。
然后它还要经过urldecode处理以后,再反向解析成中文字符串。就是你看到的这个样子'\xe5\x85\x88\xe7\x94\x9f' 这就是name参数的内存格式。
假如控制台只能接受和显示GB2312、 要对这个字符串做 utf-8 转GBK的处理才能显示出来了。

这是两个关于汉字编码的地址可做参考
http://www.cnblogs.com/ttltry-air/p/3325543.html
https://www.zhihu.com/question/26921730

您好,python requests接口测试,根据postman得到的参数payload里还有中文,执行后会报错。UnicodeEncodeError: 'latin-1' codec can't encode characters in position 179-182: Body ('并驾齐驱') is not valid Latin-1. Use body.encode('utf-8') if you want to send it encoded in UTF-8.请问大牛是怎么解决的?

yecp 回复

我也遇到了同样的问题,我的中文是一个value值,执行unittest就报错

yecp 回复

post里面把data=payload改成data=payload.encode('utf-8')试试!

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册