Overriding python threading.Thread.run ()

Angesichts der Python-Dokumentation für Thread.run() :

Sie können diese Methode in einer Unterklasse überschreiben. Die standard run () -Methode ruft das auf den Konstruktor des Objekts übergebene kündbare Objekt als Zielargument, falls vorhanden, mit sequentiellen und Keyword-Argumenten aus den args- und kwargs-Argumenten auf.

Ich habe den folgenden Code konstruiert:

 class DestinationThread(threading.Thread): def run(self, name, config): print 'In thread' thread = DestinationThread(args = (destination_name, destination_config)) thread.start() 

Aber wenn ich es ausführen, bekomme ich folgende Fehlermeldung:

 Exception in thread Thread-1: Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/threading.py", line 522, in __bootstrap_inner self.run() TypeError: run() takes exactly 3 arguments (1 given) 

Es scheint, dass ich etwas offensichtliches fehlt, aber die verschiedenen Beispiele, die ich mit dieser Methodik gesehen habe. Letztendlich versuche ich, den String und das Wörterbuch einfach in den Thread zu übergeben, wenn der Konstruktor nicht der richtige Weg ist, sondern um eine neue Funktion zu machen, um die Werte vor dem Starten des Threads einzustellen, bin ich offen dafür.

Irgendwelche Vorschläge, wie man das am besten erreichen kann?

6 Solutions collect form web for “Overriding python threading.Thread.run ()”

Du brauchst wirklich keine Unterklasse Thread. Der einzige Grund, warum die API dies unterstützt, ist es, es für Leute, die aus Java kommen, bequemer zu machen, wo es nur der Weg ist, es gut zu tun.

Das Muster, das wir Ihnen empfehlen, ist, eine Methode an den Thread-Konstruktor zu übergeben und rufen .start() einfach .start() .

  def myfunc(arg1, arg2): print 'In thread' print 'args are', arg1, arg2 thread = Thread(target=myfunc, args=(destination_name, destination_config)) thread.start() 

Hier ist ein Beispiel für die Übergabe von Argumenten mit Threading und nicht erweitern init :

 import threading class Example(threading.Thread): def run(self): print '%s from %s' % (self._Thread__kwargs['example'], self.name) example = Example(kwargs={'example': 'Hello World'}) example.start() example.join() 

Und hier ist ein Beispiel mit mutliprocessing:

 import multiprocessing class Example(multiprocessing.Process): def run(self): print '%s from %s' % (self._kwargs['example'], self.name) example = Example(kwargs={'example': 'Hello World'}) example.start() example.join() 

Die Dokumentation von threading.Thread scheint zu bedeuten, dass jede unbenutzte Position und Keyword args übergeben werden, um zu laufen. Sie sind nicht.

Alle zusätzlichen Positions-Args und Keyword- kwargs sind in der Tat von der Standard- threading.Thread.__init__ Methode gefangen, aber sie werden NUR an eine Methode übergeben, die mit target= keyword angegeben ist. Sie werden NICHT an die run() Methode übergeben.

In der Tat, die Threading-Dokumentation an macht deutlich, dass es die Standard- run() -Methode ist, die die mitgelieferte target= -Methode mit den gefangenen kwargs und kwargs :

"Sie können diese Methode in einer Unterklasse überschreiben. Die Standard-run () -Methode ruft das auf das Konstruktor des Objekts übergebene aufrufbare Objekt als Zielargument, falls vorhanden, mit sequentiellen und Keyword-Argumenten aus den Args- und kwargs-Argumenten auf."

Um etwas von der Verwirrung darüber zu behandeln, ob eine überschriebene run() -Methode zusätzliche Argumente verwendet, ist hier eine Implementierung einer überschriebenen run() -Methode, die das macht, was die Methode von threading.Thread geerbt hat.

Beachten Sie, dies nur zu sehen, wie man überschreiben run() ; Es ist nicht sinnvoll, ein sinnvolles Beispiel zu sein. Wenn alles, was Sie tun möchten, eine Zielfunktion mit sequentiellen und / oder Keyword-Argumenten aufruft, ist es nicht notwendig, eine Unterklasse zu haben. Dies wurde z. B. in der Antwort von Jerub auf diese Frage hervorgehoben.

Der folgende Code unterstützt sowohl Python v2 als auch v3.

Obwohl vor allem der Zugriff auf die Mangled-Attributnamen im Python 2-Code hässlich ist, bin mir kein anderer Weg bekannt, auf diese Attribute zuzugreifen (lass mich wissen, ob du einen kennst …):

 import sys import threading class DestinationThread(threading.Thread): def run(self): if sys.version_info[0] == 2: self._Thread__target(*self._Thread__args, **self._Thread__kwargs) else: # assuming v3 self._target(*self._args, **self._kwargs) def func(a, k): print("func(): a=%s, k=%s" % (a, k)) thread = DestinationThread(target=func, args=(1,), kwargs={"k": 2}) thread.start() thread.join() 

Es druckt (getestet mit Python 2.6, 2.7 und 3.4 unter Windows 7):

 func(): a=1, k=2 

Sie definieren die Run-Methode, um 3 Argumente zu akzeptieren, aber Sie rufen es mit einem Argument an (python nennt es mit dem Verweis auf das Objekt).

Sie müssen die Argumente anstelle von __init__ .

Oder mache die __init__ Methode stattdessen die Argumente an.

Wenn du deinen objektorientierten Ansatz behalten willst und auch Argumente geführt hast, kannst du folgendes machen:

 import threading class Destination: def run(self, name, config): print 'In thread' destination = Destination() thread = threading.Thread(target=destination.run, args=(destination_name, destination_config)) thread.start() 

Wie oben erwähnt, könnte es auch mit partial

 from functools import partial import threading class Destination: def run(self, name, config): print 'In thread' destination = Destination() thread = threading.Thread(target=partial( destination.run, destination_name, destination_config)) thread.start() 

Der Vorteil, dies zu tun, im Vergleich zu einem rein funktionalen Ansatz ist, dass es Ihnen erlaubt, Ihre anderen existierenden objektorientierten Code gleich zu halten. Die einzige Änderung ist, dass es nicht Unterklasse Thread, die sollte nicht eine große Sache, da pro threading.Thread Dokumentation:

Überschreiben nur die init () und run () Methoden dieser Klasse

Wenn du das Thread überschreibst, so dass du aus deiner Unterklasse auf das Thread-Objekt zugreifen könntest, dann würde ich empfehlen, nur threading.currentThread () aus deinem Objekt zu verwenden. Auf diese Weise sehe du den Namensraum des Threads aus deinem eigenen und nach dem "Zen von Python" von Tim Peters:

Namensräume sind eine hupende Idee – lasst uns mehr davon machen!

  • Python: separate Prozesse protokollieren zu derselben Datei?
  • Wie man einen nicht blockierenden URL-Abruf in Python macht
  • Ein Mehrteil- / Gewinde-Downloader über Python?
  • Opencv python Multi Threading Video Capture
  • Hintergrund-Thread mit QThread in PyQt
  • Warum Python Multiprocessing Manager produzieren Threading Locks?
  • Wie kann ich keine mit Signalen über Threads senden?
  • Beim Importieren einen neuen Thread
  • Flasche mit CherryPy verhält sich nicht mehrfach, wenn der gleiche Endpunkt aufgerufen wird
  • Wie Kraft ein Python-Skript alle x Sekunden
  • Wann funktioniert eine Numba-Funktion?
  • Python ist die beste Programmiersprache der Welt.