on button clicked multiprocessing threading

Programmierung für GNOME und GTK+, GUI-Erstellung mit Glade.
Benutzeravatar
martinjo
User
Beiträge: 153
Registriert: Dienstag 14. Juni 2011, 20:03

on button clicked multiprocessing threading

Beitragvon martinjo » Dienstag 13. Juni 2017, 16:06

Hallo

Ich arbeite mit Python 2.7 und Gtk3

Hier möchte ich gerne eine Funktion über einen Gtk.Button aufrufen. Diese soll dann im Hintergrund laufen. Ich habe es schon mal zum laufen bekommen aber inzwischen leider nicht mehr. Es wird bei beiden Beispielen die gesamte Anwendung blockiert.

  1. from threading import Thread
  2. from multiprocessing import Process
  3.  
  4.  
  5. # Beispiel 1 -  threading
  6. button.connect("clicked", self.on_run_background_process_clicked)
  7. def on_run_background_process_clicked(slelf, widget):
  8.         Thread(target=Shipping().add_shipping_numbers()).start()
  9.  
  10.  
  11. # Beispiel 2 - multiprocessing
  12. button.connect("clicked", self.on_run_background_process_clicked)
  13. def on_run_background_process_clicked(slelf, widget):
  14.     a = Process(name='add_shipping_numbers', target=Shipping().add_shipping_numbers())
  15.     a.start()
  16.     a.join()


Es wäre noch super eine Möglichkeit zu haben, zu prüfen ob ein Prozess schon läuft, denn 2x sollte der natürlich nicht laufen um Probleme mit Überschneidung zu vermeiden.
Zuletzt geändert von Anonymous am Dienstag 13. Juni 2017, 16:16, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

Re: on button clicked multiprocessing threading

Beitragvon BlackJack » Dienstag 13. Juni 2017, 16:19

@martinjo: Wenn ich mal raten müsste, dann ist gibt die `add_shipping_numbers()`-Methode *nicht* die Methode oder Funktion zurück die ausgeführt werden soll, sondern sie *ist* die Methode die ausgeführt werden soll‽ Dann darfst Du sie nicht aufrufen und den Rückgabewert an `Thread()` oder `Process()` übergeben, sondern die Methode selbst. Aufgerufen wird sie dann ja von `Thread`/`Process`.
Benutzeravatar
martinjo
User
Beiträge: 153
Registriert: Dienstag 14. Juni 2011, 20:03

Re: on button clicked multiprocessing threading

Beitragvon martinjo » Dienstag 13. Juni 2017, 16:33

Vielen Dank, Problem gelöst :-)

Eine Frage noch, kann ich auch verhindern, dass ein Prozess mehrmals parallel läuft? Ich kann ja sowohl "Thread" als auch "Process" einen Namen geben, kann man nicht anhand von diesem prüfen ob der Prozess bereits läuft?
BlackJack

Re: on button clicked multiprocessing threading

Beitragvon BlackJack » Dienstag 13. Juni 2017, 16:51

@martinjo: Ich würde mir das einfach merken, denn normalerweise deaktiviert man bei solchen Sachen ja auch den Startbutton, damit der Benutzer das gar nicht noch einmal starten *kann* solange es läuft.
Benutzeravatar
martinjo
User
Beiträge: 153
Registriert: Dienstag 14. Juni 2011, 20:03

Re: on button clicked multiprocessing threading

Beitragvon martinjo » Mittwoch 14. Juni 2017, 15:16

Hallo, da habe ich doch dann das selbe Problem, dass ich feststellen muss wann ein Prozess zu Ende ist um den Knopf wieder frei zu geben.
BlackJack

Re: on button clicked multiprocessing threading

Beitragvon BlackJack » Mittwoch 14. Juni 2017, 15:46

@martinjo: Über das Ende informiert doch hoffentlich der Prozess. :-) Ich würde ja `concurrent.futures` verwenden. Da kann man leicht zwischen Thread und Prozess wählen, und eine Rückruffunktion registrieren wenn die Aufgabe durch ist, egal ob wegen Ergebnis/normales Ende oder wegen Ausnahme.
Benutzeravatar
__deets__
User
Beiträge: 1070
Registriert: Mittwoch 14. Oktober 2015, 14:29

Re: on button clicked multiprocessing threading

Beitragvon __deets__ » Mittwoch 14. Juni 2017, 17:09

@BlackJack: ist diese Rueckruffunktion nicht in einem extra Thread? Wenn ja, muss die natuerlich einen geeigneten Weg nutzen mit der GUI zu reden.
BlackJack

Re: on button clicked multiprocessing threading

Beitragvon BlackJack » Mittwoch 14. Juni 2017, 17:20

@__deets__: Jup, das muss man berücksichtigen.
Benutzeravatar
martinjo
User
Beiträge: 153
Registriert: Dienstag 14. Juni 2011, 20:03

Re: on button clicked multiprocessing threading

Beitragvon martinjo » Freitag 16. Juni 2017, 16:28

Hallo
Ich hab es leider nicht ganz verstanden. Der Prozess informiert mich nicht wenn er zu ende ist.
BlackJack

Re: on button clicked multiprocessing threading

Beitragvon BlackJack » Freitag 16. Juni 2017, 17:06

@martinjo: Sollte er aber. :-)
Benutzeravatar
martinjo
User
Beiträge: 153
Registriert: Dienstag 14. Juni 2011, 20:03

Re: on button clicked multiprocessing threading

Beitragvon martinjo » Dienstag 20. Juni 2017, 19:30

In wie fern meldet er sich denn zurück?

Ich starte einen Prozess, der läuft ja im Hintergrund. Wie z.B. unten das Beispiel mit Process aber ohne join dann.

Ich kann jedoch prüfen ob der Prozess läuft mit p.is_alive()

Meine Lösung inzwischen ist nicht schön, trotzdem möchte ich Sie zumindest vorstellen:

  1. # Beispiel - multiprocessing
  2. button.connect("clicked", self.on_run_background_process_clicked)
  3.  
  4. def on_run_background_process_clicked(slelf, widget):
  5.         try:
  6.             if self.p.is_alive():
  7.                 logger.warning("process is already running")
  8.                 return
  9.             else:
  10.                 raise
  11.         except:
  12.                 pass
  13.     self.p = Process(name='add_shipping_numbers', target=Shipping().add_shipping_numbers())
  14.     self.p.start()
Zuletzt geändert von Anonymous am Dienstag 20. Juni 2017, 21:04, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Benutzeravatar
__deets__
User
Beiträge: 1070
Registriert: Mittwoch 14. Oktober 2015, 14:29

Re: on button clicked multiprocessing threading

Beitragvon __deets__ » Dienstag 20. Juni 2017, 19:48

Bits du sicher, das das geht? Mir sieht das so aus als ob du die add_shipping_numbers gleich aufrufst - sind ja Klammern hinter. Das wurde ja schon besprochen...

Und statt es zu machen wie du wäre ein timer der is_alive prüft & dann den button enabled besser. Noch besser das von BJ angesprochene concurrent.futures.
BlackJack

Re: on button clicked multiprocessing threading

Beitragvon BlackJack » Dienstag 20. Juni 2017, 21:22

@martinjo: Das war wohl missveständlich von mir: Mit sollte er aber meinte ich nicht das er das schon machen sollte, sondern das er das besser machen sollte, also Du das so programmieren solltest das er das macht. Das wäre nämlich die benutzerfreundliche Variante. Also zum Beispiel ein `concurrent.futures.Future` das am Ende über eine Rückruffunktion informiert das das Ergebnis da ist. Auch wenn der Prozess kein Ergebnis hat, ist die Information das es *da* ist, ja auch eins. Ausserdem kann man da auch erfahren ob die asynchrone Funktion tatsächlich durchgelaufen ist, oder ob sie mit einer Ausnahme endete. Die Information kann ja auch nützlich sein.

``raise`` ohne Argument? Das geht nicht. Also das geht schon — es löst einen `TypeError` aus der sagt das ``raise`` ohne Argument (also implizitem `None`) nicht geht. :-D Deswegen ist ja wahrscheinlich auch das unsinnige und unsägliche ``try``/``except`` um diesen Test. Ich hoffe mal das ist da nicht nur deswegen weil das `p`-Attribut vor dem ersten Start `None` ist und man darauf kein `is_alive()` aufrufen kann. *Das* kann man ja schliesslich einfach prüfen.

  1.     def on_run_background_process_clicked(self, widget):
  2.         if self.process and self.process.is_alive():
  3.             logger.warning('process is already running')
  4.         else:
  5.             self.process = Process(target=Shipping().add_shipping_numbers)
  6.             self.process.start()
Benutzeravatar
martinjo
User
Beiträge: 153
Registriert: Dienstag 14. Juni 2011, 20:03

Re: on button clicked multiprocessing threading

Beitragvon martinjo » Donnerstag 22. Juni 2017, 11:02

Hallo

Ja, die Klammern müssen weg, versehentlich aus dem ersten Beispiel übernommen.

@BlackJack
self.process existiert ja erst nachdem die Funktion das erste mal aufgerufen wurde. Da das Programm aber viele Funktionen hat möchte ich ungern self.process bereits beim initialisieren setzen.
BlackJack

Re: on button clicked multiprocessing threading

Beitragvon BlackJack » Donnerstag 22. Juni 2017, 11:44

@martinjo: Das ist ein guter Weg sich ins Knie zu schiessen — Klassen mit vielen Methoden die jeweils ihre eigenen Attribute erzeugen können. Nach der Abarbeitung von `__init__()` sollte eine Klasse alle Attribute besitzen und in einem benutzbaren Zustand sein. Das Du die Klasse Programm nennst und die Methode Funktion, und das es davon viele gibt, legt den Verdacht nahe das Du da eigentlich einen Haufen Funktionen mit ``global`` in eine Gott-Klasse verschoben hast. Dadurch verschwindet zwar das ``global``-Schlüsselwort, aber das eigentliche, zugrunde liegende Problem damit bleibt bestehen.

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder