• 基于Flask 实现多进程并发服务


    背景:

    看了许多网上关于Flask多进程的介绍,但根本行不通(有直接用flask实现多进程的朋友,麻烦教教我哈)

    开始:

    下面是基于flask的基础web服务实现的多进程并发思路(该思路已经证明是可行的)

    功能:提取图像上的文字,实现并发

    1. 写一个flask基本服务,用于接受请求,将传来的图像随机命名为rand.jpg并存到test文件夹,不断检测result文件夹中是否存在rand.txt文件,若存在,解析rand.txt将结果返回,并删除result/rand.txt,若超时则抛错;

    2. 使用python的多进程策略,将图像提取文字的功能封装成函数,视为工人,用多进程开启多个工人,用循环让工人一直等待,直到test文件夹存在图像文件,让工人去抢工作(图像)并开始处理,这里需要用Lock的逻辑,不然工人会混乱并且浪费资源,当工人发现图像,立即锁定文件lock.txt,若发现该文件被锁定,则稍等片刻再次尝试锁定文件,直到文件没有被锁定,这时候这个工人先自己把lock.txt锁定,并且获取test文件夹中的图像列表imglist,与lock.txt的文件进行对比,遍历imglist,如果发现图像A.jpg在lock.txt中不存在,则将这个A.jpg添加到lock.txt中,并对lock.txt解除锁定,然后跳出遍历开始对将A.jpg进行处理,处理完成后将处理结果存在result/A.txt中,并删除test中的A.jpg。此时A.txt会被步骤1检测到,至此大功告成。

    注意:需要将lock.txt定期删除,否则会增加列表遍历时间,当检测文件存在时,不要立即读取文件,稍等片刻再读取,否则文件在写入的过程就去读取通常会报错

    代码:

    功能部分tyocr.py

    import cv2
    import os, fcntl, time
    import model
    from apphelper.image import union_rbox,adjust_box_to_origin
    
    imgroot = 'test'
    locktxt = 'lock.txt'
    
    def find_word(imgpath):
        img = cv2.imread(imgpath)
        _,result,angle= model.model(img,detectAngle=True,config=dict(MAX_HORIZONTAL_GAP=50,MIN_V_OVERLAPS=0.6,MIN_SIZE_SIM=0.6,TEXT_PROPOSALS_MIN_SCORE=0.1,TEXT_PROPOSALS_NMS_THRESH=0.3,TEXT_LINE_NMS_THRESH = 0.7),leftAdjust=True,rightAdjust=True,alph=0.01)
        result = union_rbox(result,0.2)
        res = [{'text':x['text'],'name':str(i),'box':{'cx':x['cx'],'cy':x['cy'],'w':x['w'],'h':x['h'],'angle':x['degree']}} for i,x in enumerate(result)]
        res = adjust_box_to_origin(img,angle, res)##修正box
        txtpath = os.path.join('result', imgpath.split('/')[1].split('.')[0] + '.txt')
    
        print(res)
        with open(txtpath, 'w') as f:
            for n in res:
                str_temp = n['text']
                f.write(str_temp)
                f.write('
    ')
            f.close()
        if os.path.exists(imgpath):
            os.remove(imgpath)
    
    def get_worklist():
        list_ = os.listdir(imgroot)
        if len(list_) == 0:
            if os.path.exists(locktxt):
                os.remove(locktxt)
            return None
        with open(locktxt, 'a') as f:
            try:
                fcntl.flock(f,fcntl.LOCK_EX|fcntl.LOCK_NB)
                try:
                    list_unwork = os.listdir(imgroot)
                    list_working = []
                    if os.path.exists(locktxt):
                        for n in open(locktxt):
                            list_working.append(n[:-1])
                    for m in list_unwork:
                        if not m in list_working:
                            f.write(m)
                            f.write('
    ')
                            fcntl.flock(f, fcntl.LOCK_UN)
                            f.close()
                            return os.path.join(imgroot, m)
                        else:
                            continue
                    return None
                except:
                    fcntl.flock(f, fcntl.LOCK_UN) ## 一旦程序出现问题,就解锁不要耽误其他进程
                    return None
            except:
                return None
    
    if __name__ == "__main__":
        print('======= s t a r t =========')
        while True:
            imgpath = None
            imgpath = get_worklist()
            if imgpath == None:
                continue
            else:
                find_word(imgpath)
    

     开启多进程main.py

    import os
    from multiprocessing import Process
    
    def fun1():
        os.system("python tyocr.py")
    
    if __name__ == "__main__":
        list_ = []
        for i in range(4):
            list_.append(Process(target = fun1))
        for p in list_:
            p.start()
    

    web服务server.py

    import os, requests, time
    from flask import Flask,render_template,request
    import base64
    import random
    
    def getRandomSet(bits):
        num_set = [chr(i) for i in range(48,58)]
        char_set = [chr(i) for i in range(97,123)]
        total_set = num_set + char_set
        value_set = "".join(random.sample(total_set, bits))
        return value_set
    
    app = Flask(__name__)
    imgroot = 'test'
    txtroot = 'result'
    
    @app.route("/tyocr", methods = ['GET', 'POST'])
    def tyocr():
        if request.method == "POST":
            imgbase64 = request.form.get('imgbase64')
            imgdata = base64.b64decode(imgbase64)
            randname = getRandomSet(15)
            imgrandpath = os.path.join(imgroot, randname + '.jpg')
            txtrandpath = os.path.join(txtroot, randname + '.txt')
            file = open(imgrandpath,'wb')
            file.write(imgdata)
            file.close()
            count = 0
            while True:
                time.sleep(0.01)
                count = count + 0.01
                if count > 20:
                    return {'sign':-1, 'text':'time out'}
                if os.path.exists(txtrandpath):
                    time.sleep(0.1)
                    str1 = ''
                    for n in open(txtrandpath):
                        str1 = str1 + n
                    print(str1)
                    os.remove(txtrandpath)
                    return {'sign':0, 'text':str1}
    
                else:
                    continue
        else:
            return "<h1>Image find words! please use post</h1>"
    
    if __name__ == "__main__":
        host = '0.0.0.0'
        port = '8090'
        app.run(debug=True, host=host, port=port)
    
  • 相关阅读:
    表单
    超链接
    图像
    表格
    排列清单控制标
    HTML基本结构
    如何快速查看网页源代码
    TOR的使用
    google搜索新姿势
    [NOIP2017]列队
  • 原文地址:https://www.cnblogs.com/niulang/p/13785887.html
Copyright © 2020-2023  润新知