Search code examples
pythonpython-3.xmultithreadingpython-multithreading

Python threading TypeError too many arguments


I have the following code trying to recreate the Reader Writer problem (note I haven't used the locks yet):

import threading

class ReadWrite:
    threadList = [0] * 20

    def __init__(self, origData):
        self.readerLock = threading.Lock()
        self.writerLock = threading.Lock()
        self.data = origData
        self.readerCount = 0

    def acquireReadLock(self):
        self.readerLock.acquire()

    def releaseReadLock(self):
        self.readerLock.release()

    def acquireWriteLock(self):
        self.writerLock.acquire()

    def releaseWriteLock(self):
        self.writerLock.release()

    def printData(self, threadName):
        print(threadName, ' printed ', self.data)

    def modifyData(self, threadName, newData):
        print(threadName, ' changed ', self.data, ' to ', newData)
        self.data = newData
    
    def run(self):
        for x in range(20):
            threadString = 'Thread' + str(x)
            if x % 6:
                self.threadList[x] = threading.Thread(target=self.printData, args=(threadString))
            else:
                newData = self.data + str(x)
                self.threadList[x] = threading.Thread(target=self.modifyData, args=(threadString, newData))
            self.threadList[x].start()

        for x in range(20):
            self.threadList[x].join()
myVar = ReadWrite('Hello')
myVar.run()

When I run this, I get the following errors

Exception in thread Thread-9:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
TypeError: printData() takes 2 positional arguments but 8 were given
Exception in thread Thread-10:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
TypeError: printData() takes 2 positional arguments but 8 were given
Exception in thread Thread-11:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
TypeError: printData() takes 2 positional arguments but 8 were given

I'm only passing one argument which is the threadString into the printData function. I was wondering where it's getting the additional arguments from? All help would be greatly appreciated! I'm new to multithreading and the threading library in Python so I'm doing this problem as a learning exercise.

I've tried implementing the threading outside of the class and have it call the function using the class instance:

threadList = [0] * 20
myVar = ReadWrite('Hello')

for x in range(20):
            threadString = 'Thread' + str(x)
            if x % 6:
                threadList[x] = threading.Thread(target=myVar.printData, args=(threadString))
            else:
                newData = self.data + str(x)
                threadList[x] = threading.Thread(target=myVar.modifyData, args=(threadString, newData))
            threadList[x].start()

        for x in range(20):
            threadList[x].join()

But I got the same error.


Solution

  • You need to pass threadString in a tuple. As you have it, it's just unpacking the threadString itself. Change the line from:

    self.threadList[x] = threading.Thread(target=self.printData, args=(threadString))
    

    to

    self.threadList[x] = threading.Thread(target=self.printData, args=(threadString,))