Python, getting 'NoneType' object has no attribute 'something' - 退出多线程程序时出错

Python, getting 'NoneType' object has no attribute 'something' - error when exiting a multithreaded program

我有一个多线程程序,但在使用键盘中断时无法完全退出它时遇到了一些问题。有没有办法即使有多个线程我也可以干净地退出程序 运行ning?

这是从主线程关闭程序时给出错误的代码。

        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() > 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()

这是整个错误消息:

线程 Thread-1 中的异常(很可能在解释器关闭期间引发):

回溯(最近调用最后):

文件“/usr/lib/python2.7/threading.py”,第 810 行,在 __bootstrap_inner

文件“/usr/lib/python2.7/threading.py”,第 763 行,在 运行

文件 "trafgen6.py",第 592 行,在 init

文件“/usr/lib/python2.7/sched.py”,第 117 行,在 运行

文件 "trafgen6.py",第 598 行,单轮

类型'exceptions.AttributeError': 'NoneType'对象没有属性's'

编辑这是客户端的其余代码-class

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()

编辑 2 这是主线程的代码

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() > 0:
                calculator(mode)

这里是主线程的代码

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()

threading.local() 在调用时创建一个特定于当前 运行 线程的对象。您只需在主线程上执行一次,然后与所有其他线程共享。一旦解释器开始关闭并且超出范围,其他线程的引用就会损坏。

threadLocal = threading.local() 必须移动到您的实际线程中,即 Client.__init__ 的顶部。