Dlaczego otrzymuję błąd AttributeError: Obiekt nie ma atrybutu [zamknięte]

82

Mam klasę MyThread. W tym mam próbkę metody. Próbuję uruchomić go z tego samego kontekstu obiektu. Proszę spojrzeć na kod:

class myThread (threading.Thread):
    def __init__(self, threadID, name, counter, redisOpsObj):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter
        self.redisOpsObj = redisOpsObj

    def stop(self):
        self.kill_received = True

    def sample(self):
        print "Hello"

    def run(self):
        time.sleep(0.1)
        print "\n Starting " + self.name
        self.sample()

Wygląda na bardzo proste, prawda? Ale kiedy go uruchamiam, pojawia się ten błąd

AttributeError: 'myThread' object has no attribute 'sample'Teraz mam tę metodę, właśnie tam. Więc co się stało? Proszę pomóż

Edycja: to jest ślad stosu

Starting Thread-0

Starting Thread-1
Exception in thread Thread-0:
Traceback (most recent call last):
File "/usr/lib/python2.6/threading.py", line 525, in __bootstrap_inner
self.run()
File "./redisQueueProcessor.py", line 51, in run
self.sample()
AttributeError: 'myThread' object has no attribute 'sample'

Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python2.6/threading.py", line 525, in __bootstrap_inner
self.run()
File "./redisQueueProcessor.py", line 51, in run
self.sample()
AttributeError: 'myThread' object has no attribute 'sample'

Ja to tak nazywam

arThreads = []
maxThreads = 2;

for i in range( maxThreads ):
    redisOpsObj = redisOps()
    arThreads.append( myThread(i, "Thread-"+str(i), 10, redisOpsObj) )

Przepraszamy, nie mogę wysłać kodu klasy redisOps. Ale mogę cię zapewnić, że działa dobrze

Odcienie88
źródło
Czy opublikowałby cały błąd ze stosem wywołań?
lenistwo
czy mógłbyś dodać kod, jak dzwonisz?
Babu,
2
Brakuje jakiegoś kodu. Ten fragment działa dobrze dla mnie.
ThirdOne
2
Jest mi ogromnie przykro. Tak, moje wcięcie zostało oszukane. Całkowicie nowicjusz w Pythonie. Więc mógł przegapić krytyczność wcięcia.
Shades88
podczas kodowania Pythona należy wybrać opcję „Pokaż tabulatory i spacje” w edytorze kodu
vanduc1102

Odpowiedzi:

94

Twoje wcięcie jest błędne i pomieszałeś tabulatory i spacje. Uruchom skrypt, python -ttaby zweryfikować.

Ignacio Vazquez-Abrams
źródło
Dzięki za ten otwieracz do oczu. Teraz to rozumiem. Przepraszam za głupie pytanie i zbyt długie wyjaśnienie takiego pytania;)
Shades88
3
Czy mógłbyś mi powiedzieć, jakie jest znaczenie „Uruchom skrypt za pomocą python -tt, aby zweryfikować”?
akshay_rahar
9
@akshay_rahar:python -tt script.py
Ignacio Vazquez-Abrams
1
Więc co robi ten magiczny parametr -tt? Nie znalazłem tego w dokumentach
Łukasz Nojek
10
Aktualizacja: -ttflaga nie występuje w Pythonie 3, była w Pythonie 2.
Łukasz Nojek
13

Jeśli używasz Pythona 3+, może się to również zdarzyć, jeśli używasz prywatnych zmiennych, które zaczynają się od podwójnego podkreślenia, np. Self .__ yourvariable. Po prostu coś, na co warto zwrócić uwagę dla niektórych z was, którzy mogą napotkać ten problem.

Timothy Mugayi
źródło
Czy jest to udokumentowane w PIP?
przerywany
1
po prostu natknąłem się na problem i znalazłem ten komentarz, dlaczego mieliby to tak zaprojektować?
matthewhang
1
Jest to udokumentowane tutaj: docs.python.org/3/tutorial/classes.html#private-variables
Mohit
12

Tego rodzaju błędy są powszechne w przypadku wielowątkowości Pythona. Dzieje się tak, że po usunięciu tłumacza odpowiedni moduł ( myThreadw tym przypadku) przechodzi coś w rodzaju del myThread.

Wywołanie self.sample()jest z grubsza równoważne z myThread.__dict__["sample"](self). Ale jeśli jesteśmy w trakcie sekwencji zrywania interpretera, to jego własny słownik znanych typów mógł już zostać myThreadusunięty, a teraz jest w zasadzie a NoneType- i nie ma atrybutu „sample”.

Trevor
źródło
7

Może się to również zdarzyć, jeśli używasz slotów w klasie i nie dodałeś jeszcze tego nowego atrybutu do slotów.

class xyz(object):
"""
class description

"""

__slots__ = ['abc', 'ijk']

def __init__(self):
   self.abc = 1
   self.ijk = 2
   self.pqr = 6 # This will throw error 'AttributeError: <name_of_class_object> object has no attribute 'pqr'
Mitendra
źródło
2

Otrzymałem ten błąd dla scenariusza wielowątkowego (szczególnie w przypadku ZMQ). Okazało się, że gniazdo nadal jest połączone w jednym wątku, podczas gdy inny wątek już zaczął przesyłać dane. Zdarzenia, które wystąpiły z powodu innego wątku, próbowały uzyskać dostęp do zmiennych, które nie zostały jeszcze utworzone. Jeśli twój scenariusz obejmuje wielowątkowość i jeśli coś działa, jeśli dodasz trochę opóźnienia, możesz mieć podobny problem.

Shital Shah
źródło
1

Python chroni tych członków, zmieniając wewnętrznie nazwę, tak aby zawierała nazwę klasy. Możesz uzyskać dostęp do takich atrybutów, jak object._className__attrName.

Shyam Gupta
źródło
0

Napotkałem również ten sam błąd. Jestem pewien, że moje wgłębienie nie miało żadnego problemu. Dopiero ponowne uruchomienie sprzedaży Pythona rozwiązało problem.

Mohammad Sadoughi
źródło
Możesz publikować polecenia ponownego uruchomienia lub cokolwiek zrobiłeś. Może to być pomocne dla początkujących.
Khan
0

Ten sam błąd wystąpił, gdy miałem inną zmienną o nazwie mythread. Ta zmienna nadpisała to i dlatego mam błąd

remobob
źródło
-3

Nie możesz uzyskać dostępu poza prywatnymi polami zajęć. pola prywatne zaczynają się od __. na przykład -

class car:
    def __init__(self):
        self.__updatesoftware()

    def drive(self):
        print("driving")

    def __updatesoftware(self):
        print("updating software:")

obj = car()
obj.drive()  
obj.__updatesoftware()  ## here it will throw an error because 

__updatesoftware to metoda prywatna.

mukesh yadav
źródło
3
Autor nie próbuje uzyskać dostępu do metody prywatnej, pytanie również ma ponad 6 lat i zostało już rozwiązane, więc nie ma potrzeby ponownego odpowiadania na nie.
Johan