Multithreading Kivy和烧瓶螺纹在蟒蛇中相互阻塞2

Multithreading Kivy和烧瓶螺纹在蟒蛇中相互阻塞2,multithreading,python-2.7,flask,kivy,Multithreading,Python 2.7,Flask,Kivy,我有以下设置:Kivy 1.11.1、Flask 1.1.1和Python 2.7.13。我想获取一个JSON请求,但我被困在Flask应用程序无法在Kivy GUI运行时获取请求的地方。即使在单独的线程中运行,它们也会相互阻塞 主api脚本eg_api.py: #!/usr/bin/python2.7 python2.7 # -*- coding: utf-8 -*- # kivy modules first, if not Kivy may cause problems import ki

我有以下设置:Kivy 1.11.1、Flask 1.1.1和Python 2.7.13。我想获取一个JSON请求,但我被困在Flask应用程序无法在Kivy GUI运行时获取请求的地方。即使在单独的线程中运行,它们也会相互阻塞

主api脚本eg_api.py:

#!/usr/bin/python2.7 python2.7
# -*- coding: utf-8 -*-

# kivy modules first, if not Kivy may cause problems
import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.screenmanager import ScreenManager, Screen
kivy.require('1.10.0')

# common modules
import re
import sys
import time
import signal
import threading
from datetime import datetime

# Flask & similar modules
from flask import Flask
from flask import request
from flask_restful import reqparse, abort, Api, Resource
from flask_httpauth import HTTPBasicAuth
import json, ast
import urlparse
import eventlet
from eventlet import wsgi

# imports from other files
from eg_wrapper import Actions

# async server setup
eventlet.monkey_patch()
app = Flask(__name__)
api = Api(app)
auth = HTTPBasicAuth()

# user access setup
USER_DATA = {
    "admin": "SuperSecretPwd"
}

# global variable
data_json = None

@auth.verify_password
def verify(username, password):
    if not (username and password):
        return False
    return USER_DATA.get(username) == password

def start_Flask():
    print("Starting Flask...")
    #app.run(port=5000, debug=False)     #specify separate port to run Flask app
    wsgi.server(eventlet.listen(('', 5000)), app)     # deploy as an eventlet WSGI server

def signal_handler(signal, frame):
    print " CTRL + C detected, exiting ... "
    exit(0)


#######################   flask classes   #########################
class Load(Resource):
    @auth.login_required
    def post(self):
        print "**********  class Load(Resource): *****************"
        data = request.json
        print data
        lw = Actions()
        data_json = lw.Parse_Load_Request(data)
        res = {'data': data_json}
        return res, 201


#######################   resource calls   #######################
api.add_resource(Load, '/load')


########################## kivy screen classes ###############################
class MainScreen(Screen):
    pass


########################## kivy popup classes ###############################

# main screen        
class MainScreen(Screen):
    def __init__(self, **kwargs):
        self.name="MAIN SCREEN"
        super(Screen, self).__init__(**kwargs)

# popup        
class MessageBox10(Popup):
    def __init__(self, obj, **kwargs):
        super(MessageBox10, self).__init__(**kwargs)
        self.obj = obj

# popup        
class MessageBox20(Popup):
    def __init__(self, obj, **kwargs):
        super(MessageBox20, self).__init__(**kwargs)
        self.obj = obj

class Kivy(App):
    w_MessageBox10_1 = "Message_10_1"
    w_MessageBox10_2 = "Message_10_2"
    w_MessageBox10_3 = "Message_10_3"
    w_MessageBox10_4 = "Message_10_4"
    w_MessageBox20_1 = "Message_20_1"
    w_MessageBox20_2 = "Message_20_2"
    w_MessageBox30_1 = "Message_30_1"
    w_MessageBox30_2 = "CONFIRM"
    w_MessageBox30_3 = "CANCEL"

    def do(self):
        print "do something"

    def cancel(self):
        print "load cancelled by user"

    def exit(self):
        print "exiting..."
        exit(1)

    def enter(self):
        # open the init file and write the parameters
        print "********** def enter(self): popup = MessageBox20(self) *************************"
        popup = MessageBox20(self)
        popup.open()

    def build(self):
        sm = Builder.load_string("""

ScreenManager
    MainScreen:
        size_hint: 1, .7
        auto_dismiss: False
        title: app.w_MessageBox10_1       
        title_align: "center"

        BoxLayout:
            orientation: "vertical"
            Label:
                text: app.w_MessageBox10_2
            BoxLayout:
                orientation: "horizontal"
                spacing: 10
                size_hint: 1, .5
                Button:
                    text: app.w_MessageBox30_2  # CONFIRM
                    on_press:
                        app.enter()
                Button:
                    text: app.w_MessageBox30_3  # CANCEL
                    on_press:
                        app.exit()

<MessageBox20>:
    size_hint: 1, .7
    auto_dismiss: False
    title: app.w_MessageBox20_1       
    title_align: "center"

    BoxLayout:
        orientation: "vertical"
        Label:
            text: app.w_MessageBox20_2
        BoxLayout:
            orientation: "horizontal"
            spacing: 10
            size_hint: 1, .5
            Button:
                text: app.w_MessageBox30_2  # "CONFIRM"
                on_press:
                    app.do()
                    root.dismiss()
            Button:
                text: app.w_MessageBox30_3  # "CANCEL"
                on_press:
                    app.cancel()
                    root.dismiss()  

        """)

        return sm


if __name__ == '__main__':    

    #CTRL+C signal handler
    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)

    # start the first thread
    t1 = threading.Thread(target=start_Flask)
    t1.start()

    # start the second thread
    t2 = threading.Thread(target=Kivy().run)
    t2.start()

    # join the two threads
    t1.join()
    t2.join()
程序

我运行eg_api.py,Flask和Kivy以线程的形式启动。他们站起来运行,eventlet正在监听,第一个弹出窗口出现在Kivy窗口中。然后我发送请求

输出

(py2) parovelb@Latitude-E6510:~/Desktop/Python2$ python eg_api.py 
[INFO   ] [Logger      ] Record log in /home/parovelb/.kivy/logs/kivy_19-12-23_34.txt
[INFO   ] [Kivy        ] v1.10.1
[INFO   ] [Python      ] v2.7.15rc1 (default, Nov 12 2018, 14:31:15) 
[GCC 7.3.0]
[INFO   ] [Factory     ] 194 symbols loaded
[INFO   ] [Image       ] Providers: img_tex, img_dds, img_sdl2, img_pil, img_gif (img_ffpyplayer ignored)
[INFO   ] [Text        ] Provider: sdl2
Starting Flask...
 (15549) wsgi starting up on http://0.0.0.0:5000
[INFO   ] [Window      ] Provider: sdl2(['window_egl_rpi'] ignored)
[INFO   ] [GL          ] Using the "OpenGL" graphics system
[INFO   ] [GL          ] Backend used <gl>
[INFO   ] [GL          ] OpenGL version <3.3 (Compatibility Profile) Mesa 19.0.8>
[INFO   ] [GL          ] OpenGL vendor <nouveau>
[INFO   ] [GL          ] OpenGL renderer <NVA8>
[INFO   ] [GL          ] OpenGL parsed version: 3, 3
[INFO   ] [GL          ] Shading version <3.30>
[INFO   ] [GL          ] Texture max size <8192>
[INFO   ] [GL          ] Texture max units <16>
[INFO   ] [Window      ] auto add sdl2 input provider
[INFO   ] [Window      ] virtual keyboard not allowed, single mode, not docked
[INFO   ] [Base        ] Start application main loop
[INFO   ] [GL          ] NPOT texture support is available
********** def enter(self): popup = MessageBox20(self) *************************
do something
exiting...
[INFO   ] [Base        ] Leaving application in progress...
 (15549) accepted ('192.168.3.88', 53418)
**********  class Load(Resource): *****************
{u'position': u'b1', u'tasks': [{u'code': u'24258146312', u'actionDescription': u'Preleva 20ml di glucosio dalla sacca', u'barcode': u'000001', u'results': [u'returnCode'], u'actions': [{u'returnCode': u'200', u'type': u'CONFIRM', u'label': u'Conferma'}, {u'returnCode': u'400', u'type': u'ABORT', u'label': u'Annulla'}], u'itemName': u'Glucosio 100ml'}, {u'code': u'24258146313', u'actionDescription': u'Leggi il barcode e il codice RFID', u'itemName': u'Glucosio 100ml', u'barcode': u'000001', u'results': [u'returnCode', u'barcode', u'rfid'], u'actions': [{u'returnCode': u'200', u'type': u'CONFIRM', u'label': u'Conferma'}, {u'returnCode': u'400', u'type': u'ABORT', u'label': u'Annulla'}], u'type': u'BARCODE_CHECK'}, {u'code': u'24258146314', u'itemName': u'Glucosio 100ml', u'actionDescription': u'Posiziona la sacca nello slot 1', u'actions': [{u'returnCode': u'200', u'type': u'CONFIRM', u'label': u'Conferma'}, {u'returnCode': u'400', u'type': u'ABORT', u'label': u'Annulla'}], u'results': [u'returnCode']}], u'weight': u'133.15'}
********** def Parse_Load_Request(self, r): *****************************
********** def Parse_Load_Request(self, r): print data without uni-code chars *****************************
********** def Parse_Load_Request(self, r): print keys for data *****************************
['position', 'tasks', 'weight']
 192.168.3.88 - - [23/Dec/2019 11:08:44] "POST /load HTTP/1.1" 201 247 0.004312
(py2)parovelb@Latitude-E6510:~/Desktop/Python2$python eg_api.py
[INFO][Logger]记录登录/home/parovelb/.kivy/logs/kivy_19-12-23_34.txt
[INFO][Kivy]v1.10.1
[INFO][Python]v2.7.15rc1(默认,2018年11月12日,14:31:15)
[GCC 7.3.0]
[信息][工厂]加载了194个符号
[信息][图像]提供商:img_-tex、img_-dds、img_-sdl2、img_-pil、img_-gif(img_-ffpyplayer忽略)
[信息][文本]提供商:sdl2
启动烧瓶。。。
(15549)wsgi在上启动http://0.0.0.0:5000
[INFO][Window]提供程序:sdl2(['Window\u egl\u rpi']已忽略)
[信息][GL]使用“OpenGL”图形系统
[信息][GL]已使用后端
[信息][GL]OpenGL版本
[信息][GL]OpenGL供应商
[INFO][GL]OpenGL渲染器
[信息][GL]OpenGL解析版本:3,3
[信息][GL]明暗处理版本
[信息][GL]纹理最大大小
[信息][GL]纹理最大单位
[信息][窗口]自动添加sdl2输入提供程序
[信息][窗口]不允许使用虚拟键盘,单模,未对接
[INFO][Base]启动应用程序主循环
[INFO][GL]提供NPOT纹理支持
**********def enter(自我):弹出=消息框20(自我)*************************
做点什么
退出。。。
[INFO][Base]正在退出应用程序。。。
(15549)接受('192.168.3.88',53418)
**********类负载(资源):*****************
{u'position':u'b1',u'tasks':[{u'code':u'24258146312',u'actionDescription':u'Preleva 20ml di glucosio dalla sacca',u'barcode':u'000001',u'results':[u'returnCode'],u'actions':[{u'returnCode':u'200',u'type':u'CONFIRM',u'label':u'Conferma',{u'returnCode u'400',u'type':u'ABORT':u'label':u'Annuala'],u'itemName':u'Glucosio 100ml',{u'code':u'24258146313',u'actionDescription':u'Leggi-il-barcode e-il-codice-RFID',u'itemName':u'Glucosio 100ml',u'barcode':u'returnCode',u'barcode',u'RFID',u'actions:[{u'returnCode':u'200',u'type':u'CONFIRM',u'label':u'ma',{u'returnCode':u'400',u'type':u'ABORT',u'label':u'Canalla'}],u'type':u'BARCODE'u CHECK',{u'code':u'24258146314',u'itemName':u'Glucosio 100ml',u'actionDescription':u'Posiziona la sacca nello slot 1',u'actions':[{u'returnCode:u'200',u'type':u'CONFIRM',u'label':u'ma',{u'returnCode':u'400',u'type':u'ABORT',u'label':u'Canella'}],u'results':[u'returnCode']}],u'weight':u'133.15'}
**********def解析加载请求(self,r):*****************************
**********def Parse_Load_请求(self,r):打印不带uni code字符的数据*****************************
**********def Parse_Load_Request(self,r):打印数据键*****************************
[‘位置’、‘任务’、‘重量’]
192.168.3.88---[23/Dec/2019 11:08:44]“发布/加载HTTP/1.1”201 247 0.004312
问题


当我发送请求时,Flask没有获取请求。当我按下第一个弹出窗口的按钮时,Flask仍然没有获取请求。当我按下第二个弹出窗口的按钮时,Flask仍然没有获取请求。Kivy会阻止Flask,无论我如何启动线程。我检查了,但我没有帮助。我做错了什么?

I这不是问题的确切答案,但它是烧瓶阻塞Kivy的替代解决方案,反之亦然。我尝试了多重处理,它似乎能起到作用。希望它能帮助一些人,如果一些专家编码人员决定升级,欢迎这样做

代码

#!/usr/bin/python2.7 python2.7
# -*- coding: utf-8 -*-

# kivy modules first, if not Kivy may cause problems
import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.screenmanager import ScreenManager, Screen
kivy.require('1.10.0')


# common modules
import sys
import signal
from multiprocessing import Process


# Flask & similar modules
from flask import Flask
from flask_restful import reqparse, abort, Api, Resource
import eventlet
from eventlet import wsgi


# async server setup
eventlet.monkey_patch()
app = Flask(__name__)
api = Api(app)


def start_Flask():
    print("Starting Flask...")
    # deploy as an eventlet WSGI server on port 5000
    wsgi.server(eventlet.listen(('', 5000)), app)     


def signal_handler(signal, frame):
    # for fetching CTRL+C and relatives
    print " CTRL + C detected, exiting ... "
    exit(1)


# Kivy screen class
class MainScreen(Screen):
    def __init__(self, **kwargs):
        self.name="MAIN SCREEN"
        super(Screen, self).__init__(**kwargs)


# Kivy app class
class Kivy(App):
    w_MessageBox10_1 = "MAIN SCREEN"
    w_MessageBox10_2 = "One golden glance of what should be"
    w_MessageBox30_2 = "CHORUS"
    w_MessageBox30_3 = "EXIT"


    # exit button action   
    def exit(self):
        print "exiting... one shaft of light will show the way..."
        p1.terminate()  # terminate Flask by pressing on cancel
        exit(1)


    # do magic button action
    def do_magic(self):
        # your code goes here or maybe not
        print "***** it's a kind of magic *************************"


    # Kivy UI builder file
    def build(self):
        sm = Builder.load_string("""

ScreenManager
    MainScreen:
        size_hint: 1, .7
        auto_dismiss: False
        title: app.w_MessageBox10_1       
        title_align: "center"

        BoxLayout:
            orientation: "vertical"
            Label:
                text: app.w_MessageBox10_2
            BoxLayout:
                orientation: "horizontal"
                spacing: 10
                size_hint: 1, .5
                Button:
                    text: app.w_MessageBox30_2  # DO MAGIC
                    on_press:
                        app.do_magic()
                Button:
                    text: app.w_MessageBox30_3  # EXIT
                    on_press:
                        app.exit()


        """)

        return sm


if __name__ == '__main__':    

    # #CTRL+C signal handler
    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)

    global p1
    p1 = Process(target=start_Flask)    # assign Flask to a process
    p1.start()                          # run Flask as process
    Kivy().run()                        # run Kivy UI

你能不能创建一个最小的例子,让别人可以复制/粘贴来查看同一个问题?@Erik,我按照你的建议尽可能地缩小它。问题是行与行之间的
Starting Flask…(15549)wsgi在http://0.0.0.0:5000
[INFO][Base]正在保留应用程序…
没有
*******def Parse\u Load\u Request*********
#!/usr/bin/python2.7 python2.7
# -*- coding: utf-8 -*-

# kivy modules first, if not Kivy may cause problems
import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.screenmanager import ScreenManager, Screen
kivy.require('1.10.0')


# common modules
import sys
import signal
from multiprocessing import Process


# Flask & similar modules
from flask import Flask
from flask_restful import reqparse, abort, Api, Resource
import eventlet
from eventlet import wsgi


# async server setup
eventlet.monkey_patch()
app = Flask(__name__)
api = Api(app)


def start_Flask():
    print("Starting Flask...")
    # deploy as an eventlet WSGI server on port 5000
    wsgi.server(eventlet.listen(('', 5000)), app)     


def signal_handler(signal, frame):
    # for fetching CTRL+C and relatives
    print " CTRL + C detected, exiting ... "
    exit(1)


# Kivy screen class
class MainScreen(Screen):
    def __init__(self, **kwargs):
        self.name="MAIN SCREEN"
        super(Screen, self).__init__(**kwargs)


# Kivy app class
class Kivy(App):
    w_MessageBox10_1 = "MAIN SCREEN"
    w_MessageBox10_2 = "One golden glance of what should be"
    w_MessageBox30_2 = "CHORUS"
    w_MessageBox30_3 = "EXIT"


    # exit button action   
    def exit(self):
        print "exiting... one shaft of light will show the way..."
        p1.terminate()  # terminate Flask by pressing on cancel
        exit(1)


    # do magic button action
    def do_magic(self):
        # your code goes here or maybe not
        print "***** it's a kind of magic *************************"


    # Kivy UI builder file
    def build(self):
        sm = Builder.load_string("""

ScreenManager
    MainScreen:
        size_hint: 1, .7
        auto_dismiss: False
        title: app.w_MessageBox10_1       
        title_align: "center"

        BoxLayout:
            orientation: "vertical"
            Label:
                text: app.w_MessageBox10_2
            BoxLayout:
                orientation: "horizontal"
                spacing: 10
                size_hint: 1, .5
                Button:
                    text: app.w_MessageBox30_2  # DO MAGIC
                    on_press:
                        app.do_magic()
                Button:
                    text: app.w_MessageBox30_3  # EXIT
                    on_press:
                        app.exit()


        """)

        return sm


if __name__ == '__main__':    

    # #CTRL+C signal handler
    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)

    global p1
    p1 = Process(target=start_Flask)    # assign Flask to a process
    p1.start()                          # run Flask as process
    Kivy().run()                        # run Kivy UI