AttributeError: 'int' object has no attribute 'getattr'

86 阅读2分钟

在使用多进程编程时,遇到一个错误:AttributeError: 'int' object has no attribute 'getattr'。错误发生在以下代码中:

class worker_manager:
    # ...
    names = {'one': 'import_1', 'two': 'import_2'}
    def __init__(self):
        self.children = {}
    def generate(self, control_queue, threadName, runNum):
        name = self.names[threadName]
        target = i.getattr(name) #THis is throwing the error
        print ("Starting %s number %d") % (name, runNum)
        p = multiprocessing.Process(target=target, args=(control_queue, runNum))
        self.children[threadName] = p
        p.start()
    def terminate(self, threadName):
        self.children[threadName].join()

if __name__ == '__main__':
    # Establish communication queues
    control = multiprocessing.Queue()
    manager = worker_manager()    
    runNum = int(raw_input("Enter a number: ")) 
    threadNum = int(raw_input("Enter number of threads: "))
    threadName = raw_input("Enter number: ")
    thread_Count = 0

    print ("Starting threads") 

    for i in range(threadNum):
        if threadName == 'three':
            manager.generate(control, 'one', i)
            manager.generate(control, 'two', i)
        manager.generate(control, threadName, i)
        thread_Count = thread_Count + 1              
        if threadName == 'three':
            thread_Count = thread_Count + 1 

    time.sleep(runNum)#let threads do their thing

    print ("Terminating threads")     

    for i in range(thread_Count):
        control.put("t1kill")
        control.put("t2kill")
    if threadName == 'three':
        manager.terminate('one')
        manager.terminate('two')
    else:
        manager.terminate(threadName)   

解决方案

错误的原因是,在 target = i.getattr(name) 这行代码中,i 是一个整数,而整数没有 getattr 属性。

要解决这个问题,需要将 i 替换为一个对象,该对象具有 getattr 属性。一种方法是使用 getattr 函数,如下所示:

target = getattr(i, name)

另一种方法是使用 operator.attrgetter 函数,如下所示:

target = operator.attrgetter(name)(i)

代码例子

使用 getattr 函数修改后的代码如下:

class worker_manager:
    # ...
    names = {'one': 'import_1', 'two': 'import_2'}
    def __init__(self):
        self.children = {}
    def generate(self, control_queue, threadName, runNum):
        name = self.names[threadName]
        target = getattr(i, name) #THis is throwing the error
        print ("Starting %s number %d") % (name, runNum)
        p = multiprocessing.Process(target=target, args=(control_queue, runNum))
        self.children[threadName] = p
        p.start()
    def terminate(self, threadName):
        self.children[threadName].join()

if __name__ == '__main__':
    # Establish communication queues
    control = multiprocessing.Queue()
    manager = worker_manager()    
    runNum = int(raw_input("Enter a number: ")) 
    threadNum = int(raw_input("Enter number of threads: "))
    threadName = raw_input("Enter number: ")
    thread_Count = 0

    print ("Starting threads") 

    for i in range(threadNum):
        if threadName == 'three':
            manager.generate(control, 'one', i)
            manager.generate(control, 'two', i)
        manager.generate(control, threadName, i)
        thread_Count = thread_Count + 1              
        if threadName == 'three':
            thread_Count = thread_Count + 1 

    time.sleep(runNum)#let threads do their thing

    print ("Terminating threads")     

    for i in range(thread_Count):
        control.put("t1kill")
        control.put("t2kill")
    if threadName == 'three':
        manager.terminate('one')
        manager.terminate('two')
    else:
        manager.terminate(threadName)   

使用 operator.attrgetter 函数修改后的代码如下:

class worker_manager:
    # ...
    names = {'one': 'import_1', 'two': 'import_2'}
    def __init__(self):
        self.children = {}
    def generate(self, control_queue, threadName, runNum):
        name = self.names[threadName]
        target = operator.attrgetter(name)(i) #THis is throwing the error
        print ("Starting %s number %d") % (name, runNum)
        p = multiprocessing.Process(target=target, args=(control_queue, runNum))
        self.children[threadName] = p
        p.start()
    def terminate(self, threadName):
        self.children[threadName].join()

if __name__ == '__main__':
    # Establish communication queues
    control = multiprocessing.Queue()
    manager = worker_manager()    
    runNum = int(raw_input("Enter a number: ")) 
    threadNum = int(raw_input("Enter number of threads: "))
    threadName = raw_input("Enter number: ")
    thread_Count = 0

    print ("Starting threads") 

    for i in range(threadNum):
        if threadName == 'three':
            manager.generate(control, 'one', i)
            manager.generate(control, 'two', i)
        manager.generate(control, threadName, i)
        thread_Count = thread_Count + 1              
        if threadName == 'three':
            thread_Count = thread_Count + 1 

    time.sleep(runNum)#let threads do their thing

    print ("Terminating threads")     

    for i in range(thread_Count):
        control.put("t1kill")
        control.put("t2kill")
    if threadName == 'three':
        manager.terminate('one')
        manager.terminate('two')
    else:
        manager.terminate(threadName)   

修改后的代码解决了 AttributeError: 'int' object has no attribute 'getattr' 错误,程序可以正常运行。