У меня есть App
, который открывает ModalView
всплывающее окно из Thread
с помощью Clock.schedule_once()
и использует Queue
для ожидания закрытия всплывающего окна.Это прекрасно работает около 90% времени.Но иногда поток ожидает отклонения без отображения всплывающего окна.Этот сбой происходит только при запуске exe
, созданного Pyinstaller
, и только с первой попытки (т. Е. При первом нажатии кнопки «Выполнить тест»).Если первая попытка завершится успешно, все следующие попытки также будут успешными.
Я использую:
- Pyinstaller версия 3.3.dev0 + 483c819
- Windows 10
Я занимаюсь разработкой с использованием Python 3, но Pyinstaller
создает код для запуска Python 2.7.14.Выходные данные отладки показывают только ожидаемые различия между успехом и неудачей.
Этот пример взят из гораздо более сложного приложения.Если кто-то может увидеть проблему или порекомендовать более надежный способ открытия ModalView
из Thread
, пожалуйста, сообщите мне.
main.py:
import threading
from kivy.app import App
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.modalview import ModalView
from kivy.compat import PY2
if PY2:
from Queue import Queue
else:
from queue import Queue
class TestLayout(FloatLayout):
def __init__(self):
super(TestLayout, self).__init__()
def do_test(self, *arg):
self.th = AThread()
self.th.start()
class MyPopup(object):
def __init__(self, callback):
self.buttonCallback = callback
dismiss_button = Button(text='Dismiss')
dismiss_button.bind(on_press=self.butt)
self.popup = ModalView(size_hint=(.5, .5), auto_dismiss=False)
self.popup.add_widget(dismiss_button)
def butt(self, *args):
if self.popup is not None:
self.popup.dismiss()
if self.buttonCallback is not None:
self.buttonCallback()
def open(self, *args):
self.popup.open()
class AThread(threading.Thread):
def __init__(self):
super(AThread, self).__init__()
self.daemon = True
self.pop = None
self.queue = None
def run(self):
print('running')
self.queue = Queue()
self.pop = MyPopup(lambda: self.queue.put(None, False))
Clock.schedule_once(self.pop.open) # This should open the popup, but occasionally it does not
print('waiting')
self.queue.get(True)
print('done waiting')
self.queue = None
root = Builder.load_string( '''
TestLayout:
Button:
text: 'Run Test'
on_press: root.do_test()
''')
class testApp(App):
def build(self):
return root
testApp().run()
main.spec:
# -*- mode: python -*-
from kivy.deps import sdl2, glew
block_cipher = None
a = Analysis(['main.py'],
pathex=['C:\\Users\\John\\PyCharmProjects\\popupbug'],
binaries=[],
datas=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
*[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)],
name='Test',
debug=True,
strip=False,
upx=True,
runtime_tmpdir=None,
console=True)