zoukankan      html  css  js  c++  java
  • 基于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)
    
  • 相关阅读:
    HDU 2196 Computer
    HDU 1520 Anniversary party
    POJ 1217 FOUR QUARTERS
    POJ 2184 Cow Exhibition
    HDU 2639 Bone Collector II
    POJ 3181 Dollar Dayz
    POJ 1787 Charlie's Change
    POJ 2063 Investment
    HDU 1114 Piggy-Bank
    Lca hdu 2874 Connections between cities
  • 原文地址:https://www.cnblogs.com/niulang/p/13785887.html
Copyright © 2011-2022 走看看