Thread AttributeError

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Gremlin
User
Beiträge: 166
Registriert: Freitag 28. Mai 2010, 23:49

Code: Alles auswählen

from threading import Thread


class WorkerThread(Thread):
    def run(self):
        # Original ausm threading Modul
        try:
            if self.__target:
                self.__target(*self.__args, **self.__kwargs)
        finally:
            # Avoid a refcycle if the thread is running a function with
            # an argument that has a member that points to the thread.
            del self.__target, self.__args, self.__kwargs


def worker():
    while True: pass


thread = WorkerThread(target=worker)
thread.start()
Resultiert in:
Exception in thread Thread-1:
Traceback (most recent call last):
File "E:\Python27\lib\threading.py", line 552, in __bootstrap_inner
self.run()
File "G:\TEMP\blub.py", line 13, in run
del self.__target, self.__args, self.__kwargs
AttributeError: _WorkerThread__target
Kann mir das einer erklären?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Im Original ist es nur ein Unterstrich und nicht zwei. Was versuchst du dort eigentlich? Wenn du den Thread in einer Klasse haben willst, dann kannst du auch direkt

Code: Alles auswählen

class Worker(threading.Thread):
    def run(self):
        while True:
            pass
schreiben.

Sebastian
Das Leben ist wie ein Tennisball.
Gremlin
User
Beiträge: 166
Registriert: Freitag 28. Mai 2010, 23:49

Ahhhh... Es handelt sich übrigens um Python 2.7 ...denn bei mir im threading Modul sinds wirklich zwei Unterstriche.

Code: Alles auswählen

# Main class for threads

class Thread(_Verbose):

    ...

    def __init__(self, group=None, target=None, name=None,
                 args=(), kwargs=None, verbose=None):
        assert group is None, "group argument must be None for now"
        _Verbose.__init__(self, verbose)
        if kwargs is None:
            kwargs = {}
        self.__target = target
        ...
Und zu deiner Frage was ich eigentlich vorhabe:

Code: Alles auswählen

class WorkerThread(Thread):
    def __init__(self, group=None, target=None, name=None, args=(), kwargs=None):
        Thread.__init__(self, group, target, name, args, kwargs)
        self._target = target
        self._args = args
        self._kwargs = kwargs or {}
        self._aborted = False
    
    def run(self):
        try:
            if self._target:
                self._target(self, *self._args, **self._kwargs)
        finally:
            # Avoid a refcycle if the thread is running a function with
            # an argument that has a member that points to the thread.
            del self._target, self._args, self._kwargs
    
    def should_abort(self):
        return self._aborted
    
    def abort(self):
        self._aborted = True
        try:
            self.join()
        except RuntimeError:
            if self.is_alive():
                raise
Das funktioniert. Aber mein oben gepostetes MiniBeispiel tuts eben nicht. Wenn mir jetzt jemand erklärt warum ich die Originalattribute nicht verwenden kann, bin ich glücklich. :)
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Gremlin hat geschrieben:Wenn mir jetzt jemand erklärt warum ich die Originalattribute nicht verwenden kann, bin ich glücklich. :)
Grundsätzlich sollte man schon Attribute mit einfachem führenden Unterstrich nicht anfassen, da diese laut Konvention nicht als Teil der öffentlichen API gesehen werden. Bei Attributen mit doppelten führenden Unterstrichen bekommt man sogar extra noch mal was um die Ohren gehauen. Stichwort: name mangling.

Lass mal folgenden Code laufen:

Code: Alles auswählen

from __future__ import print_function

class Base(object):
    def __init__(self):
        self.value1 = 'value 1'
        self._value2 = 'value 2'
        self.__value3 = 'value 3'

class Descendant(Base):
    def show(self):
        print(self.value1)
        print(self._value2)
        print(self.__value3)

inst = Descendant()
inst.show()
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

/me hat ja bereits geschrieben, was die doppelten Unterstriche andeuten. Wenn du deren Bedeutung nicht kennst, solltest du wirklich noch einmal überlegen was du dort tust. Doppelte Unterstriche sind ein ganz deutlicher Hinweis darauf, dass man das Attribut nur anfassen sollte, wenn man wirklich genau weiß was man dort eigentlich tut.

Sehe ich das richtig, dass du bei deinem WorkerThread einfach alles aus Thread hineinkopiert hast?
Das Leben ist wie ein Tennisball.
Gremlin
User
Beiträge: 166
Registriert: Freitag 28. Mai 2010, 23:49

Oha, die Bedeutung der Unterstriche vor einem Attribut ist mir ja eigentlich schon bekannt, aber ich war bisher der Meinung dass das nicht mehr als nur eine Richtlinie für Programmierer ist und nicht dass der Interpreter tatsächlich diese ebenfalls "beachtet". Naja, wieder was dazu gelernt. Danke.

@EyDu
Nein ich habe nicht alles kopiert. Ich habe nur die run-Methode kopiert und gebe dann dem target als erstes Argument die Instanz des Threads. Damit prüfe ich dann per "should_abort" im target ob die Verarbeitung abgebrochen werden soll oder nicht.
Antworten