2016-10-12 5 views
0

Ich mache ein kleines Programm, das die neuesten Einnahmen aus einem Webshop bekommt, wenn es mehr als die vorherige Menge einen Ton macht, verwende ich Pyglet, aber ich bekomme Fehler, weil es nicht vom Hauptthread aufgerufen wird. Ich würde gerne wissen, wie man eine Methode im Hauptthread aufruft. siehe Fehler unter:Wie ruft man eine Methode auf dem GUI-Thread auf?

'thread that imports pyglet.app' RuntimeError: EventLoop.run() must be called from the same thread that imports pyglet.app

def work(): 
     threading.Timer(5, work).start() 
     file_Name = "save.txt" 
     lastRevenue = 0 
     data = json.load(urllib2.urlopen('')) 
     newRevenue = data["revenue"] 
     if (os.path.getsize(file_Name) <= 0): 
      with open(file_Name, "wb") as f: 
       f.write('%d' % newRevenue) 
       f.flush() 
     with open(file_Name, "rb") as f: 
      lastRevenue = float(f.readline().strip()) 
      print lastRevenue 
      print newRevenue 
      f.close() 
      if newRevenue > lastRevenue: 
       with open(file_Name, "wb") as f: 
        f.write('%f' % newRevenue) 
        f.flush() 
        playsound() 


    def playsound(): 
     music = pyglet.resource.media('cash.wav') 
     music.play() 
     pyglet.app.run()  

    work() 

Antwort

0

Es ist nicht besonders merkwürdig. work wird als separater Thread ausgeführt, von dem pyglet importiert wurde.

pyglet.app Wenn importiert importiert eine Menge von Kontextvariablen und was nicht. Ich sage was nicht, weil ich mich eigentlich nicht darum gekümmert habe, genauer zu untersuchen, was es tatsächlich aufbaut.

Und OpenGL kann Dinge nicht aus seinem eigenen Kontext ausführen (der Haupt-Thread, wo es sich befindet). Da darf man nicht auf OpenGL von einem Nachbar-Thread herumstochern. Wenn das Sinn macht.

Wenn Sie jedoch Ihre eigene .run()-Funktion erstellen und eine klassenbasierte Methode zum Aktivieren von Pyglet verwenden, können Sie die GUI aus dem Thread starten.

Dies ist ein funktionierendes Beispiel dafür, wie Sie es einrichten könnten:

import pyglet 
from pyglet.gl import * 
from threading import * 

# REQUIRES: AVBin 
pyglet.options['audio'] = ('alsa', 'openal', 'silent') 

class main(pyglet.window.Window): 
    def __init__ (self): 
     super(main, self).__init__(300, 300, fullscreen = False) 
     self.x, self.y = 0, 0 

     self.bg = pyglet.sprite.Sprite(pyglet.image.load('background.jpg')) 
     self.music = pyglet.resource.media('cash.wav') 
     self.music.play() 
     self.alive = 1 

    def on_draw(self): 
     self.render() 

    def on_close(self): 
     self.alive = 0 

    def render(self): 
     self.clear() 
     self.bg.draw() 
     self.flip() 

    def run(self): 
     while self.alive == 1: 
      self.render() 

      if not self.music.playing: 
       self.alive = 0 
      # -----------> This is key <---------- 
      # This is what replaces pyglet.app.run() 
      # but is required for the GUI to not freeze 
      # 
      event = self.dispatch_events() 

class ThreadExample(Thread): 
    def __init__(self): 
     Thread.__init__(self) 
     self.start() 

    def run(self): 
     x = main() 
     x.run() 

Test_One = ThreadExample() 

Beachten Sie, dass Sie immer noch den eigentlichen GUI-Code aus dem Thread starten müssen.

ich empfehlen Sie diesen STATT THO

Sehen als Mischfäden und GUI nennt, ist ein rutschiger Abhang, würde ich vorschlagen, dass Sie mit einem vorsichtigeren Weg gehen.

from threading import * 
from time import sleep 

def is_main_alive(): 
    for t in enumerate(): 
     if t.name == 'MainThread': 
      return t.isAlive() 

class worker(Thread): 
    def __init__(self, shared_dictionary): 
     Thread.__init__(self) 
     self.shared_dictionary 
     self.start() 

    def run(self): 
     while is_main_alive(): 
      file_Name = "save.txt" 
      lastRevenue = 0 
      data = json.load(urllib2.urlopen('')) 
      newRevenue = data["revenue"] 
      if (os.path.getsize(file_Name) <= 0): 
       with open(file_Name, "wb") as f: 
        f.write('%d' % newRevenue) 
        f.flush() 
      with open(file_Name, "rb") as f: 
       lastRevenue = float(f.readline().strip()) 
       print lastRevenue 
       print newRevenue 
       f.close() 
       if newRevenue > lastRevenue: 
        with open(file_Name, "wb") as f: 
         f.write('%f' % newRevenue) 
         f.flush() 
         #playsound() 
         # Instead of calling playsound() here, 
         # set a flag in the shared dictionary. 
         self.shared_dictionary['Play_Sound'] = True 
      sleep(5) 

def playsound(): 
    music = pyglet.resource.media('cash.wav') 
    music.play() 
    pyglet.app.run()  

shared_dictionary = {'Play_Sound' : False} 
work_handle = worker(shared_dictionary) 

while 1: 
    if shared_dictionary['Play_Sound']: 
     playsound() 
     shared_dictionary['Play_Sound'] = False 
    sleep(0.025) 

Es ist ein grober Entwurf dessen, was Sie suchen.
Grundsätzlich eine Art Ereignis-/Flag-gesteuertes Backend, das der Thread und die GUI verwenden können, um miteinander zu kommunizieren.

Im Wesentlichen haben Sie einen Worker-Thread (genau wie Sie zuvor), überprüft alle 5 Sekunden, welche Datei Sie wollen, und wenn es newRevenue > lastRevenue erkennt, wird es ein bestimmtes Flag auf True setzen. Ihre Hauptschleife erkennt diese Änderung, gibt einen Ton wieder und setzt das Flag auf False zurück.

Ich habe auf keinen Fall irgendeine Fehlerbehandlung hier absichtlich eingeschlossen, wir sind hier, um zu helfen und nicht ganze Lösungen zu erstellen. Ich hoffe, das hilft dir in die richtige Richtung.

+0

thx dies ist ein großer Einblick, wie man mit Multi-Threading in Python umgehen, ich bin kein Experte, aber ich habe ähnliche Dinge mit C# getan, nur nie in Python hilft dies. Jetzt ist es das zu implementieren. – Youngdev

+0

thx das ist ein großer Einblick, wie mit Multithreading in Python umzugehen, ich bin kein Experte, aber ich habe ähnliche Dinge mit C# getan, nur nie in Python hilft dies. Jetzt ist es das zu implementieren. Danke – Youngdev

+0

@Youngdev Sie sind willkommen, vergessen Sie nicht, irgendeine Antwort als eine angemessene Lösung zu markieren, wenn Sie denken, dass meine oder irgendeine andere Antwort Ihnen genug geholfen hat! Einen schönen Tag und viel Glück :) – Torxed

Verwandte Themen