I get this error during a lengthy match in my strategy game, Table Wars. It seems to occur whenever there are many units on the battlefield. Here is the traceback:
Traceback (most recent call last):
File "C:\Users\Oventoaster\Desktop\Games\Table Wars\Table Wars.py", line 727, in <module>
main()
File "C:\Users\Oventoaster\Desktop\Games\Table Wars\Table Wars.py", line 131, in main
RedTeam.update()
File "C:\Python27\lib\site-packages\pygame\sprite.py", line 399, in update
for s in self.sprites(): s.update(*args)
File "C:\Users\Oventoaster\Desktop\Games\Table Wars\Table Wars.py", line 372, in update
self.attack()
File "C:\Users\Oventoaster\Desktop\Games\Table Wars\Table Wars.py", line 393, in attack
self.target.health -= self.attack_damage
AttributeError: 'NoneType' object has no attribute 'health'
The exception seems to appear in the targeting and attacking codes, so I will post them here:
def move_toward(self, target):
if self.target is None:
self.rect.move_ip(1, 0)
def update(self):
self.find_target()
self.move_toward(self.target)
self.attack()
if self.health <= 0:
self.kill()
def find_target(self):
if self.target is not None: return
for enemy in BluTeam.sprites():
if enemy.rect.centerx - self.rect.centerx <= self.range and enemy.rect.centery - self.rect.centery <= self.range:
self.target = enemy
return
self.target = None
def attack(self):
global REDGOLD
global BLUECOMMAND
if self.target is None: return
if self.target.health <= 0:
REDGOLD += self.target.reward
BLUECOMMAND += self.target.cmdback
self.target = None
if not self.cooldown_ready(): return
self.target.health -= self.attack_damage
def cooldown_ready(self):
now = pygame.time.get_ticks()
if now - self.attack_last >= self.attack_cooldown:
self.attack_last = now
return True
return False
How do I fix this?
Explanation of a common error or how to better understand a simple traceback to debug my program:
Traceback gives you the callstack and points to the error raises in which function. Nothin special here
Friendly interpreter gives the statement causing the error. This is important as it means the error raised is related to this line of code.
Here we are. The error is
AttributeError; the doc is pretty clear about it: I’m trying to read the value of or I’m trying to assign to a variable that is not a member of the related object.What is my object ? It is a
'NoneType' object; we don’t have the name, but we have its type. The object we have an issue with isNoneType, thus it is the special objectNone.What is the error with this
Noneobject ? It doesn’t have a'health'attribute is saying the Traceback. So, we are accessing the attributehealthsomewhere in the line of code the error raises, and this is called on aNoneobject.Now we are almost all set:
self.target.healthis the only location in the error line we usehealth, thus it meansself.targetisNone. Now I look at the source code I try to understand why it could be, even if I put a check at the beginning at the function against it. It leads to the fact I must set it toNonesomehow after that line.All of this reasoning steps lead to the short answer:
It means
self.targetisNone. The error comes from your code: