如果未从主模块调用wx.app.mainloop,则线程无法启动

时间:2015-10-30 01:00:31

标签: python multithreading wxpython

我希望有人可以向我解释这种行为。如果我导入一个启动wxpython接口的模块,则在app.MainLoop()结束之后,线程才能启动。最简单的例子:

simple_app.py

import wx
from threading import Thread

def test():
    from time import sleep
    while 1:
        print("thread still running")
        sleep(2)

app = wx.App() 
frame = wx.Frame(None, -1, 'simple.py')
frame.Show()
thread = Thread(target=test)
thread.setDaemon(True)
thread.start()
app.MainLoop()

main.py

import simple_app

如果你自己运行simple_app.py它工作正常,如果你运行main.py线程永远不会启动...为什么?我有一种感觉,它与线程无法锁定。

2 个答案:

答案 0 :(得分:2)

var appData = { "HomeGateway": { "company": "", "title": { "english": "", "spanish": "", "russian": "", "otherlanguage": "" }, "language": "english", "pressOKQuestion": { "left": { "english": "Press ", "spansih": "", "russian": "" }, "right": { "english": " to move to the next question", "spanish": "\" to move to the next question", "russian": "" } }, "pressOKMessage": { "left": { "english": "Press ", "spansih": "", "russian": "" }, "right": { "english": " to move on", "spanish": "\" to move to the next question", "russian": "" } }, "pressUpDown": { "left": { "english": "Please press ", "spanish": "", "russian": "" }, "middle": { "english": " or ", "spanish": "", "russian": "" }, "right": { "english": " on your remote control to select", "spanish": "", "russian": "" } }, "questions": [{ "url": "/question/1", "question": { "english": "Have you talked to your doctor today?", "spanish": "", "russian": "" }, "view": "views/question.html", "controller": "loadData", "nextPage": "#/question/2", "answers": [{ "id": 1, "answer": { "english": "Yes", "spanish": "Si", "russian": "" } }, { "answer": { "english": "No", "spanish": "No", "russian": "" }, "message": "/message/3" }] }, { "url": "/question/2", "question": { "english": "On a scale of 0-10, how bad is your pain today?", "spanish": "", "russian": "" }, "icon": "img/icons/1446585749_Doctor_Consultation.png", "iconSrc": "Broken Arm", "view": "views/question.html", "controller": "loadData", "nextPage": "#/question/3", "answers": [{ "answer": { "english": "Low", "spanish": "", "russian": "" }, "category": "1-2" }, { "answer": { "english": "Medium", "spanish": "", "russian": "" }, "category": "3-4" }, { "answer": { "english": "High", "spanish": "", "russian": "" }, "category": "5-8", "message": "/message/4" }, { "answer": { "english": "Very High", "spanish": "", "russian": "" }, "category": "9-10", "message": "/message/4" }] }, { "url": "/question/3", "question": { "english": "Please enter your systolic blood pressure.", "spanish": "", "russian": "" }, "icon": "img/icons/1446585795_Blood_Pressure_Kit.png", "iconSrc": "Blood Pressure", "view": "views/toggle-question.html", "controller": "loadData", "nextPage": "#/finished", "toggle": { "value": 100, "max": 500, "min": 50, "high": { "value": 150, "message": "/message/5" }, "low": { "value": 75, "message": "/message/6" } } }], "messages": [{ "url": "/message/1", "message": { "english": "Please talk to your nurse or doctor about why you do not want to.", "spanish": "", "russian": "" }, "icon": "img/alert-red.png", "iconSrc": "Alert", "view": "views/message.html", "controller": "loadData", "nextPage": "#/message/2" }, { "url": "/message/2", "message": { "english": "Good job!", "spanish": "", "russian": "" }, "icon": "img/icons/1446586860_Best_Choice.png", "iconSrc": "Thumbs Up!", "view": "views/message.html", "controller": "loadData", "nextPage": "#/question/1" }, { "url": "/home", "title": { "english": "Thank you for being part of today.", "spanish": "", "russian": "" }, "subtitle": { "english": "Remember this device does not take place of a personal emergency response system or a call to 911.", "spanish": "", "russian": "" }, "view": "views/home.html", "controller": "loadData", "nextPage": "#/question/1" }] } }; document.write(appData.HomeGateway.questions.length); document.write("<br/>"); document.write(appData.HomeGateway.questions); console.log(appData.HomeGateway.questions.length); console.log(appData.HomeGateway.questions);中的第二个线程在导入已经运行时尝试导入simple_app.py模块,这导致从主模块导入time时出现死锁。因为导入在导入模块时获取解释器对当前线程的导入锁定。它一直是documented

主模块中的线程可以导入其他模块,这就是为什么在主模块运行时运行simple_app的原因。将simple_app.py移动到from time import sleep中的模块级别可以解决问题。

运行以下代码有助于更好地理解问题;

my_time.py
simple_app.py

simple_app.py

from time import sleep

答案 1 :(得分:1)

这是一个非常有趣的问题。手头的问题不是很明显(至少对我而言)。

simple_app.py 的最后一行阻止,直到frame被关闭/销毁。因此,如果从 main.py 开始,只有框架关闭时,导入才会完成(并显示打印输出)。

请尝试以下方法(通常情况下,您可以更好地构建程序,以便在需要的地方启动/停止应用程序):

simple_app.py 中将最后一行更改为:

if __name__ == '__main__':
    app.MainLoop()

main.py

import wx
import simple_app
app = wx.GetApp()
app.MainLoop()

我无法告诉你为什么在直接运行和导入时确实存在差异(直接运行会显示打印结果,但导入不会)。