2013-02-04 11 views
12

जब मैं अपने अजगर कार्यक्रम मेंRuntimeError: मुख्य थ्रेड मुख्य लूप

self.client = ThreadedClient() 

फोन में नहीं है, मैं त्रुटि

"RuntimeError: main thread is not in main loop"

मैं पहले से ही कुछ Googling किया है मिलता है, लेकिन मैं एक बनाने हूँ किसी भी तरह त्रुटि ... क्या कोई मेरी मदद कर सकता है?

पूर्ण त्रुटि:

Exception in thread Thread-1: 
    Traceback (most recent call last): 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 530, in __bootstrap_inner 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 483, in run 
    File "/Users/Wim/Bird Swarm/bird_swarm.py", line 156, in workerGuiThread 
    self.root.after(200, self.workerGuiThread) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 501, in after 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1098, in _register 
    RuntimeError: main thread is not in main loop 

क्लास:

class ThreadedClient(object): 

    def __init__(self): 
     self.queue = Queue.Queue() 
     self.gui = GuiPart(self.queue, self.endApplication) 
     self.root = self.gui.getRoot() 
     self.running = True 
     self.GuiThread = threading.Thread(target=self.workerGuiThread) 
     self.GuiThread.start() 

    def workerGuiThread(self): 
     while self.running: 
      self.root.after(200, self.workerGuiThread) 
      self.gui.processIncoming()  

    def endApplication(self): 
     self.running = False 

    def tc_TekenVogel(self,vogel): 
     self.queue.put(vogel) 

class GuiPart(object): 
    def __init__(self, queue, endCommand): 
     self.queue = queue 
     self.root = Tkinter.Tk() 
     Tkinter.Canvas(self.root,width=g_groottescherm,height=g_groottescherm).pack() 
     Tkinter.Button(self.root, text="Move 1 tick", command=self.doSomething).pack() 
     self.vogelcords = {} #register of bird and their corresponding coordinates 

    def getRoot(self): 
     return self.root 

    def doSomething(): 
     pass #button action 

    def processIncoming(self): 
     while self.queue.qsize(): 
      try: 
       msg = self.queue.get(0) 
       try: 
        vogel = msg 
        l = vogel.geeflocatie() 
        if self.vogelcords.has_key(vogel): 
         cirkel = self.vogelcords[vogel] 
         self.gcanvas.coords(cirkel,l.geefx()-g_groottevogel,l.geefy()-g_groottevogel,l.geefx()+g_groottevogel,l.geefy()+g_groottevogel)    
        else: 
         cirkel = self.gcanvas.create_oval(l.geefx()-g_groottevogel,l.geefy()-g_groottevogel,l.geefx()+g_groottevogel,l.geefy()+g_groottevogel,fill='red',outline='black',width=1) 
         self.vogelcords[vogel] = cirkel 
        self.gcanvas.update() 
       except: 
        print('Failed, was van het type %' % type(msg)) 
      except Queue.Empty: 
       pass 
+0

आपके ट्रेसबैक से, ऐसा लगता है कि आप निष्पादन के मुख्य धागे से, कहीं और बना रहे थ्रेड से 'वर्करगुई थ्रेड' चला रहे हैं। मैं टीके विशेषज्ञ नहीं हूं, लेकिन त्रुटि यह सुझाव देती है कि इसकी अनुमति नहीं है (आपको टीके फ़ंक्शंस को कॉल करने के लिए मुख्य थ्रेड का उपयोग करने की आवश्यकता है, जैसे 'बाद')। – Blckknght

+0

देखें [यह प्रश्न] (http://stackoverflow.com/questions/3567238/i-need-a-little-help-with-python-tkinter-and-threading), [यह उत्तर] (http: // stackoverflow बहुसंख्यक कार्यक्रम में TkInter का उपयोग करने के बारे में कुछ विवरणों के लिए .com/a/10556698/908494) आदि। लेकिन लघु संस्करण है: केवल मुख्य धागे, अवधि में इसका उपयोग करें। – abarnert

+0

हे ब्लैककॉन्ग। क्योंकि मैं mtTkinter का उपयोग कर रहा हूँ। – user2040823

उत्तर

17

आप मुख्य थ्रेड के अलावा एक धागे में अपने मुख्य जीयूआई पाश चला रहे हैं। तुम यह नहीं कर सकते।

दस्तावेज़ कुछ जगहों पर अपमानजनक रूप से उल्लेख करते हैं कि टिंकर काफी थ्रेड सुरक्षित नहीं है, लेकिन जहां तक ​​मुझे पता है, कभी बाहर नहीं आते और कहते हैं कि आप केवल मुख्य धागे से ही बात कर सकते हैं। कारण यह है कि सच कुछ जटिल है। Tkinter खुद धागा-सुरक्षित है, लेकिन एक बहुप्रचारित तरीके से उपयोग करना मुश्किल है। इस पर आधिकारिक दस्तावेज के सबसे करीब this page हो रहा है:

Q. Is there an alternative to Tkinter that is thread safe?

Tkinter?

Just run all UI code in the main thread, and let the writers write to a Queue object…

(नमूना दिया कोड महान नहीं है, लेकिन यह है कि वे क्या सुझाव दे रहे हैं यह पता लगाने और चीजों को ठीक से करने के लिए पर्याप्त है।)

वास्तव में Tkinter, mtTkinter के लिए एक थ्रेड-सुरक्षित विकल्प है। और इसकी डॉक्स वास्तव में बहुत अच्छी तरह से स्थिति स्पष्ट:

Although Tkinter is technically thread-safe (assuming Tk is built with --enable-threads), practically speaking there are still problems when used in multithreaded Python applications. The problems stem from the fact that the _tkinter module attempts to gain control of the main thread via a polling technique when processing calls from other threads.

मेरा मानना ​​है कि यह आप वास्तव में क्या देख रहे हैं: अपने Tkinter कोड थ्रेड-1 में मुख्य थ्रेड में झांक सकते हैं करने के लिए मुख्य पाश खोजने की कोशिश कर रहा है, और यह वहाँ नहीं है।

  • क्या Tkinter डॉक्स की सिफारिश करते हैं और मुख्य थ्रेड से TkInter का उपयोग करें:

    तो, यहाँ कुछ विकल्प हैं। संभावित रूप से अपने वर्तमान मुख्य थ्रेड कोड को एक कार्यकर्ता धागे में ले जाकर।

  • यदि आप किसी अन्य लाइब्रेरी का उपयोग कर रहे हैं जो मुख्य थ्रेड (उदाहरण के लिए, twisted) लेना चाहता है, तो इसमें टिंकर के साथ एकीकृत करने का एक तरीका हो सकता है, इस मामले में आपको इसका उपयोग करना चाहिए।
  • समस्या का समाधान करने के लिए mkTkinter का उपयोग करें।

इसके अलावा, जबकि मुझे इस प्रश्न का कोई सटीक डुप्लीकेट नहीं मिला, तो SO पर कई संबंधित प्रश्न हैं। this question, this answer, और अधिक जानकारी के लिए कई और देखें।

+0

अरे abarnert। आपके उत्तर के लिए धन्यवाद। मैंने mtTkinter के साथ विकल्प के लिए उपयोग किया है। मेरा कोड चल रहा है (त्रुटियों के बिना मेरा मतलब है)। लेकिन मैं कैनवास नहीं देख सकता ... लॉगिंग में मुझे लगता है कि प्रोग्राम काम कर रहा है ... केवल विज़ुअलाइज़ेशन के बिना। आप @ https://github.com/wimhendrickx/Flocking/blob/master/bird_swarm.py कोड नहीं देख सकते हैं। अग्रिम में धन्यवाद। – user2040823

+0

@ user2040823: मैं कोड क्यों नहीं देख सकता, क्या यह सफेद पृष्ठभूमि पर सफेद पाठ में है? :) वैसे भी, मैं इसे डाउनलोड करूँगा और एक नज़र डालेंगे। – abarnert

+0

@ user2040823: ठीक है, यहां कई प्राथमिक समस्याएं हैं। सबसे पहले, आप 'root.mainloop()' कहीं भी नहीं बुला रहे हैं। दूसरा, आपके पास 'doSomething' जैसी विधियां हैं जो' self' नहीं लेती हैं (और 'staticmethod 'नहीं हैं)। तीसरा, आपका 'टिंकर' ईवेंट हैंडलर 'ईवेंट' पैरामीटर नहीं ले रहे हैं। मुझे लगता है कि इससे पहले कि आप इसके आसपास कुछ जटिल बनाने की कोशिश करें और/या mtTkinter का उपयोग करने से पहले आपको मूल टिंकर ट्यूटोरियल के माध्यम से काम करने की ज़रूरत है। यदि आपके पास कोई विशिष्ट प्रश्न हैं जो आपको उत्तर नहीं मिल पा रहे हैं, तो एक नया प्रश्न बनाएं, लेकिन मैं आपको एसओ टिप्पणियों में टिंकर मूल बातें नहीं सिखा सकता। – abarnert