title: Python, getting 'NoneType' object has no attribute 'something' - error when exiting a multithreaded program
body: <p>I have a multithreaded program and I'm having some problems with exiting it cleanly when using a keyboard interrupt. Is there a way I could exit the program cleanly even when there are multiple threads running?</p>
  
  <p>Here is the code that gives the error when the program is shut down from main thread.</p>
  
  <pre><code>        def oneround(self):
            try:
                  threadLocal.s.send(threadLocal.message)
                  threadLocal.next_time += threadLocal.delay
                  threadLocal.sch.enterabs(threadLocal.next_time, 0, self.oneround, ())
                  if self.duration != 0 and time.time() &gt; self.timeout:
                          print '\n' + 'Client socket closed after ' + str(self.duration) + ' seconds'
                          threadLocal.s.close()
                          os.kill(os.getpid(), signal.SIGINT)
            except IOError as (errno, strerror):
                  if errno == 111:
                          print 'Connection failed'
                          threadLocal.s.close()
  </code></pre>
  
  <p>Here is the whole error message:</p>
  
  <p>Exception in thread Thread-1 (most likely raised during interpreter shutdown):</p>
  
  <p>Traceback (most recent call last):</p>
  
  <p>File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner</p>
  
  <p>File "/usr/lib/python2.7/threading.py", line 763, in run</p>
  
  <p>File "trafgen6.py", line 592, in <strong>init</strong></p>
  
  <p>File "/usr/lib/python2.7/sched.py", line 117, in run</p>
  
  <p>File "trafgen6.py", line 598, in oneround</p>
  
  <p>type 'exceptions.AttributeError': 'NoneType' object has no attribute 's'</p>
  
  <p>EDIT Here is the rest of the code for client-class</p>
  
  <pre><code>class Client(QThread):
  
          def __init__(self, host, port, rate, duration, parent = None):
            super(Client, self).__init__(parent)
  
            threadLocal.sch = sched.scheduler(time.time, time.sleep)
            threadLocal.next_time = time.time()
            threadLocal.sch.enterabs(threadLocal.next_time, 0, self.oneround, ())
  
            host = host
            port = port
            speed = rate
            self.duration = duration
            threadLocal.delay = 1.0 / (speed*128)
            n = bool(True)
  
            openfile = open('1024')
            threadLocal.message = openfile.read()
  
            threadLocal.s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
            threadLocal.s.setblocking(0)
            try:
                  threadLocal.s.connect((host,port))
                  threadLocal.s.send(threadLocal.message)
                  time.sleep(0.1)
                  foo =  threadLocal.s.recvfrom(1500)
                  if foo != " ":
                          pass
            except IOError as (errno, strerror):
                  if errno == -9:
                          n = bool(False)
                          print 'Invalid address'
                          os.kill(os.getpid(), signal.SIGINT)
                  if errno == 11:
                          n = bool(False)
                          print 'Connection failed'
                          os.kill(os.getpid(), signal.SIGINT)
            if n == True:
                          self.timeout = time.time() + duration
                          threadLocal.sch.run()
  </code></pre>
  
  <p>EDIT 2 Here is the code for the main thread</p>
  
  <pre><code>if __name__ == '__main__':
          f = open('1024','w')
          for i in range(0, 962):
                  f.write('@')
          f.close()
  
          def valid_interfaces():
                  for i in ni.interfaces():
                          ip = ni.ifaddresses(i)[ni.AF_INET6][0]['addr']
                          if not ip.startswith('fe80') and not i.startswith('lo'):
                                  list.insert(0,i)
  
          parser = argparse.ArgumentParser(description='Send Ipv6 traffic through your network')
          group1 = parser.add_mutually_exclusive_group()
          group2 = parser.add_mutually_exclusive_group()
          threadLocal = threading.local()
          list = []
          valid_interfaces()
  
          group1.add_argument('-g', '--gui',
                          action='store_true', dest='gui',
                          help='Start graphical user interface. Do not use other arguments with this option')
          group1.add_argument('-s', '--server',
                          action='store_true', dest='server',
                          help='Set the program to run in server mode')
          group1.add_argument('-c', '--client',
                          action='store_true', dest='client',
                          help='Set the program to run in client mode')
          group2.add_argument('-i', '--interface',
                          action='store', dest='interface', choices=list,
                          help='Specifies the interface for server')
          group2.add_argument('-d', '--destip',
                          action='store', dest='targetip',
                          help='Sets the destination IPv6 address eg.2001:dead:beef::1')
          parser.add_argument('-p', '--port',
                          action='store', dest='port', type=int,
                          help='Specifies the port used by server or client | Default 5001', default=5001)
          parser.add_argument('-t', '--time',
                          action='store', dest='time', type=int,
                          help='Specifies how long traffic will be sent| Default (0) is unlimited', default=0)
          parser.add_argument('-r', '--rate',
                          action='store', dest='rate', type=int,
                          help='Sets the rate at which traffic will be sent | Default 1Mb/s', default=1)
          args = parser.parse_args()
  
          if args.gui:
                  app = QApplication(sys.argv)
                  app.setStyle('cleanlooks')
                  mainwindow = Application()
                  mainwindow.show()
                  sys.exit(app.exec_())
          if args.server and args.interface:
                  thread1 = threading.Thread(target=Server, args=[args.interface, args.port])
                  thread1.setDaemon(True)
                  thread1.start()
                  mode = 1
          if args.client and args.targetip:
                  thread1 = threading.Thread(target=Client, args=[args.targetip, args.port, args.rate, args.time])
                  thread1.setDaemon(True)
                  thread1.start()
                  mode = 2
          if threading.active_count() &gt; 0:
                  calculator(mode)
  </code></pre>
  
  <p>And here is the code for the main thread</p>
  
  <pre><code>class calculator(QThread):
  
          def __init__(self, mode, parent = None):
            super(calculator, self).__init__(parent)
            mb = 1048576.00
            try:
              while True:
                try:
                  sent = {}
                  recv = {}
                  inwards = []
                  out = []
                  total = []
                  n = 1
                  for i in ni.interfaces():
                          counter = psutil.net_io_counters(pernic=True)[i]
                          sent.update({n:counter.bytes_sent})
                          recv.update({n:counter.bytes_recv})
                          n +=1
                  time.sleep(1)
                  n = 1
                  for i in ni.interfaces():
                          counter = psutil.net_io_counters(pernic=True)[i]
                          totalsent = counter.bytes_sent - sent[n]
                          totalrecv = counter.bytes_recv - recv[n]
                          alldata = totalsent + totalrecv
                          self.totalout = (totalsent/mb) * 8
                          self.totalin = (totalrecv/mb) * 8
                          self.totalinout = (alldata/mb) * 8
                          inwards.insert((n-1), float("%.2f" % self.totalin))
                          out.insert((n-1), float("%.2f" % self.totalout))
                          total.insert((n-1), float("%.2f" % self.totalinout))
                          n += 1
  
                  inwards = sum(inwards)
                  out = sum(out)
                  total = sum(total)
                  sys.stdout.write('\r' + 'Outbound traffic ' + str(out) + 'Mb/s     ' + 'Inbound traffic ' + str$
                  sys.stdout.flush()
                except KeyboardInterrupt:
                  if mode == 1:
                          print '\n' + 'Server stopped'
                          raise
                  elif mode == 2:
                          print '\n' + 'Client stopped'
                          raise
            except KeyboardInterrupt:
                  sys.exit()
  </code></pre>