python3基于tonado搭建http服务

通过python3的tornado框架进行图片传输

先上完整代码

服务端

import traceback
from io import BytesIO

import tornado
import tornado.ioloop
import tornado.web
from tornado.escape import json_encode
from PIL import Image
import pickle
from base64 import b64encode
import importlib,sys
importlib.reload(sys)

class Handler(tornado.web.RequestHandler):

    def post(self):
        result = {}
        content = self.request.arguments["content"][0]
        if content is None:
            result["msg"] = "no content"
        else:
            byte_array, msg = self.content_process(content)
            result["image"] = byte_array
            result["msg"] = msg
        self.write(json_encode(result))

    def content_process(self, image_content):
        try:
            content = pickle.loads(image_content)
            image = Image.open(BytesIO(content))
            image.save("./server.png")
            image = image.rotate(90)
            
            byte_array = BytesIO()
            image.save(byte_array, format='PNG')
            byte_array = byte_array.getvalue()
            byte_array = b64encode(byte_array).decode('utf-8')
            return byte_array, "sucess"
        
        except Exception as e:
            print(traceback.format_exc())
            return str(e), "wrong"

class ImageServer(object):

    def __init__(self, port, server_address):
        self.port = port
        self.address = server_address

    def process(self):
        app = tornado.web.Application([(r"/image_server?", Handler)], )
        app.listen(self.port, address=self.address)
        tornado.ioloop.IOLoop.current().start()

if __name__ == "__main__":
    server_port = "8080"
    server_address = "192.168.10.1"
    server = ImageServer(server_port, server_address)
    print("begin server")
    server.process()

客户端

import json
import urllib
import requests
import pickle
import urllib.request
from PIL import Image
from io import BytesIO
from base64 import b64decode

def post(server_url, params):
    data = urllib.parse.urlencode(params).encode('utf-8')
    request = urllib.request.Request(server_url, data)
    return json.loads(urllib.request.urlopen(request, timeout=100).read())

def local_image(server_url, image_path):
    r_file = open(image_path, "rb")
    content = pickle.dumps(r_file.read())
    params = {"content": content}

    json_return = post(server_url, params)
    msg = json_return["msg"]

    image_bytes = b64decode(json_return["image"])
    image = Image.open(BytesIO(image_bytes))
    image.save("./user.png")

if __name__ == "__main__":
    # url = "http://localhost:8080/image_server?"
    url = "http://192.168.10.1:8080/image_server?"

    file_path = "/home/yangwn/code/server_test/46.jpg"
    local_image(url, file_path)

代码使用

代码只要修改了图片pathurl就能直接用

客户端

在主函数main中的url要适配你服务端的url,如果不知道输入什么地址,就用注释的那一行,也就是localhost,注意端口号是必要的
在进入local_image函数后,将图片数据转成字节流,并打包成dict字典的形式传到post函数
post函数里面继续把字典转成字节流,随后就上传到服务端,并等待服务端返回
接着将返回值接收,我这里返回的是一张图片和一个状态(msg),把返回的图片字节流进行转换后用BytesIO打开即可

服务端

如果前面的客户端你想要用localhost,那就把address设置为None
图片数据的传输方式都一样
就是在post中写数据的时候还用了json_encode,所以把图片用代码先转成字符了

byte_array = BytesIO()
image.save(byte_array, format='PNG')
byte_array = byte_array1.getvalue()
byte_array = b64encode(byte_array).decode('utf-8')

改进

在客户端读图的时候

r_file = open(image_path, "rb")
content = pickle.dumps(r_file.read())
params = {"content": content}

用了pickle,发现多此一举,可以改为

with open(image_path, "rb") as r_file:
	content = b64encode(r_file.read())
params = {"content": content}

这时候服务端也要适配,将

content = pickle.loads(image_content)

改为

content = b64decode(image_content)

加入神经网络

当需要输入初始化参数的时候,比如输入一个网络,但是不需要每次post都初始化网络权重,于是可以传入参数。
先修改server,先初始化网络,然后再把网络传入到handle里面

class ImageServer(object):

	def __init__(self, port, server_address):
		...
		self.model = Model()
	def process(self):
		app = tornado.web.Application([(r"/image_server?", Handler, dict(model=self.model))], )

接着再Handler里重写initialize函数,接收model

class Handler(tornado.web.RequestHandler):
	def initialize(self, model):
		self.model = model
	def conten_process(self):
		...
		predict = self.model(image)
		...
		return ...

小结:很简单的一个传输,但是找了很久好像没有可以直接拿来用的代码,就自己找找资料写了个。这个只是刚好能用的版本,中间可能还有什么bug请评论区交流

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值