我一直用python2.x,python2.x内置的字符编码方式是unicode,这就对中文的处理造成了一些困扰,尤其是在用tornado写json接口的时候,如果不做处理,出来的没有中文,都是\x4d5f之类的东西。所以通常需要这样去处理下。

除了正常的

#!/usr/bin/env python
# coding: utf-8

之外

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

是不可少的

另外,在做json.dumps的时候

self.write(response.body)

ensure_ascii=False需要有,才能正常的在json中显示中文。

这个是json包处理的问题而不是tornado处理的问题,self.write()中直接写中文则不会发生该问题。

关于tornado的httpclient异步回调功能,用一个简单的例子表达,访问baidu的IP地址查询库

class QueryIPHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    @tornado.gen.coroutine
    def get(self, *args, **kwargs):
        ip = self.get_argument('ip')
        local_ip = self.request.headers['X-Real-IP']
        conf = Config.get_config()
        base_url = 'http://apis.baidu.com/apistore/iplookupservice/iplookup'
        params = {}
        params['ip'] = ip
        try:
            http = tornado.httpclient.AsyncHTTPClient()
            headers = dict(self.request.headers)
            headers['apikey'] = conf['BAIDU_APIKEY']
            response = yield http.fetch(
                tornado.httpclient.HTTPRequest(
                    url = base_url,
                    headers=headers,
                    method='POST',
                    body=json.dumps(params, ensure_ascii=False)
                )
            )
            self.write(response.body)
        except tornado.httpclient.HTTPError, e:
            self.write(e)

 

使用web.asychronous修饰,使用gen.coroutine修饰,个人认为使用协程的好处是不用再写回调方法了。

base_url是需要访问百度api网址

params是请求参数,也就是query_string,

然后尝试使用tornado.httpclient.AsyncHTTPClient()

headers需要封装成字典类型并加入baidu的apikey。

response = yield http.fetch就是异步回调的”主体思想”,用协程和yield方式就不需要像以前一样写回调函数了。

body参数按照tornado官方文档是字符串而非字典,所以要把params变量dumps成json串传过去。

http.fetch里的可配置参数项参考

http://www.tornadoweb.org/en/stable/httpclient.html

剩下的就是异常处理了。

为何要异步非阻塞?因为tornado是单进程的,如果不异步非阻塞的话,假如访问baidu很慢,则tornado进程会被卡住,访问tornado的其他页面也会卡在那里等待,直到百度访问完成,其他页面才会响应,所同理,node也是单进程的,天生就是异步非阻塞的。相比于node,我个人觉得tornado 的好处在于,想阻塞就阻塞,想非阻塞就非阻塞,很灵活,而node想写一个同步阻塞的应用就很麻烦了。

—-20150815修订—-

通过看源码得知,字符串处理可以使用tornado.escape,如tornado.escape.json_encode(dict),但是中文也会出现问题,tornado.escape内部对json_encode的处理也是对json包的二次封装,对于包含中文的内容,需要使用tornado.escape.json_encode(dict).decode(‘unicode_escape’)处理就可以得到正确的结果。

不得不说,tornado的文档结构很好,就是说明台简单了,也缺少例子的支持,想深入了解,还是得自己看源码。

发表评论

*
*

Required fields are marked *