OxDEAD Unicornz

Have you ever seen so many?

Python. Threading. Function() Takes Exactly X Arguments (Y Given)

Was playing around running multiple threads in Python. Here is a part of script launching docker_cleanup(controller_name) function in a separate thread.

1
2
3
4
5
6
7
8
9
10
11
from threading import Thread
...
    threads = []
    for controller_name in controllers:
        # Remove container if it already exists
        t = Thread(target=docker_cleanup, args=(controller_name))
        threads.append(t)
        t.start()
    for t in threads:
        t.join()  # Block main thread while childs executed
...

it fails with the following traceback:

1
2
3
4
5
6
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 763, in run
    self.__target(*self.__args, **self.__kwargs)
TypeError: docker_cleanup() takes exactly 1 argument (11 given)

Quite confusing, huh? The point is that Thread() expects ‘args’ to be a tuple. ‘args=(controller_name)’ sends a string instead of a tulpe. Each of symbols in controller_name value was treated as a separate argument. The fix is to use ‘args=(controller_name,)’ construction that creates tuple containing one element.

Works this way:

1
2
3
4
5
6
7
8
9
10
11
from threading import Thread
...
    threads = []
    for controller_name in controllers:
        # Remove container if it already exists
        t = Thread(target=docker_cleanup, args=(controller_name,))
        threads.append(t)
        t.start()
    for t in threads:
        t.join()  # Block main thread while childs executed
...