如何使用带有Tornado的http POST发送JSON文件?

时间:2016-02-25 16:04:54

标签: python rest tornado

我尝试编写REST服务:带有http POST请求的客户端向服务器发送JSON,服务器以id响应。

基于this post代码应如下所示:

  

server.py

import tornado.httpclient
from datetime import date
import tornado.ioloop
import tornado.web
from tornado.escape import json_decode, json_encode, url_unescape

class Variazione(tornado.web.RequestHandler):

    def post(self):
        print json_decode(self.request.body)
        response = {'id': '12345'}
        self.write(response)
        tornado.ioloop.IOLoop.instance().stop()

application = tornado.web.Application([
    (r"/variazione", Variazione)
])

if __name__ == "__main__":
    application.listen(8889)
    tornado.ioloop.IOLoop.instance().start()
  

client.py

import tornado.httpclient
import json
from tornado.escape import json_decode, json_encode
from tornado import gen
import tornado.options

def read_json():
    with open('articoli.json') as json_file:
        json_data = json.load(json_file)
        print json_data
        return json_data

@tornado.gen.coroutine  
def json_fetch(http_client, body):
    response = yield http_client.fetch("http://localhost:8889/variazione", method='POST', body=body)
    raise gen.Return(response)

@tornado.gen.coroutine
def request(http_client):
    data = read_json()
    body = json_encode(data)
    http_response = yield json_fetch(http_client, body)
    print http_response.body


if __name__ == "__main__":
    tornado.options.parse_command_line()
    http_client = tornado.httpclient.AsyncHTTPClient()
    request(http_client)

但没有任何反应,服务器不会收到任何内容,也不会发生错误。

我在哪里做错了?

2 个答案:

答案 0 :(得分:0)

server.py

首先,不要在处理程序中停止IOLoop,除非你知道自己在做什么 - 它是你第一次请求后的例子,应用程序将退出。

所以看起来应该是这样的:

import tornado.ioloop
import tornado.web
from tornado.escape import json_decode, json_encode

class Variazione(tornado.web.RequestHandler):

    def post(self):
        print json_decode(self.request.body)
        response = {'id': '12345'}
        self.write(response)

application = tornado.web.Application([
    (r"/variazione", Variazione)
])

if __name__ == "__main__":
    application.listen(8889)
    tornado.ioloop.IOLoop.instance().start()

client.py

request函数为coroutine,因此无法按原样调用。它需要一个正在运行的IOLoop。您的示例中最简单的解决方案是使用run_sync,它将运行ioloop,安排协程并将等到它完成而不是停止ioloop。

为简洁起见,我删除了部分read_json(与问题无关)并将http_client移至请求。

import tornado.httpclient
import json
from tornado.escape import json_decode, json_encode
from tornado import gen
import tornado.options


@tornado.gen.coroutine  
def json_fetch(http_client, body):
    response = yield http_client.fetch("http://localhost:8889/variazione", method='POST', body=body)
    raise gen.Return(response)

@tornado.gen.coroutine
def request():
    body = '{"test_json": "ok"}'
    http_client = tornado.httpclient.AsyncHTTPClient()
    http_response = yield json_fetch(http_client, body)
    print http_response.body


if __name__ == "__main__":
    tornado.options.parse_command_line()
    tornado.ioloop.IOLoop.instance().run_sync(request)

答案 1 :(得分:0)

请勿使用此功能。

class MainHandler(tornado.web.RequestHandler):
    def post(self):
        data = self.get_argument('body', 'No data received')
        self.write(data)

application = tornado.web.Application([
    (r"/", MainHandler),
])

if __name__ == "__main__":

    def handle_request(response):
        if response.error:
            print "Error:", response.error
        else:
            print response.body
        tornado.ioloop.IOLoop.instance().stop()

    application.listen(8888)    
    test = "test data"
    http_client = tornado.httpclient.AsyncHTTPClient()
    http_client.fetch("http://0.0.0.0:8888", handle_request, method='POST', headers=None, body=test)
    tornado.ioloop.IOLoop.instance().start()

使用此:

    import urllib
    post_data = { 'data': 'test data' } #A dictionary of your post data
    body = urllib.urlencode(post_data) #Make it into a post request
    http_client.fetch("http://0.0.0.0:8888", handle_request, method='POST', headers=None, body=body) #Send it off!