Search code examples
pythonpython-3.xmultithreadingpython-multithreading

Python Thread : TypeError: __main__.generate_num() argument after * must be an iterable, not Event


I am experiment the Threads with Event

from threading import Thread, Event
import queue
import random

def generate_num(e):
    print('e',e.is_set())
    while True:
        if e.is_set():
            print('g', random.randint(15, 20))
        else:
            print('g', 0)
    
def start_generating():
    i = 0
    e = Event()
    r_thread = Thread(target=generate_num, args=(e), daemon=True).start()
    print('starting')

    while True:
        print('i', i)
        if i %5 == 0:
            e.set()
        if i ==12:
            exit(0)
        i+=1

start_generating()

My aim is that when i becomes 5 or 10, it should print the random number, otherwise it should print 0.

But, I got this error

starting
i 0
i 1
i 2
Exception in thread Thread-6 (generate_num):
Traceback (most recent call last):
i 3
i 4
i 5
i 6
i 7
i 8
i 9
File "/usr/lib/python3.10/threading.py", line 1016, in _bootstrap_inner
    i 10
iself.run()
File "/usr/lib/python3.10/threading.py", line 953, in run
11
    self._target(*self._args, **self._kwargs)
TypeError: __main__.generate_num() argument after * must be an iterable, not Event
i 12

How to solve this, thanks


Solution

  • As pointed out in the comments and also in the error the args are not an iterable or to be more specific a tuple, which is what the args argument normally should be.

    Creating a tuple with only one element needs a trailing ,

    one_element_tuple = (1,)
    

    So just do

    from threading import Thread, Event
    import queue
    import random
    
    def generate_num(e):
        print('e',e.is_set())
        while True:
            if e.is_set():
                print('g', random.randint(15, 20))
            else:
                print('g', 0)
        
    def start_generating():
        i = 0
        e = Event()
        r_thread = Thread(target=generate_num, args=(e,), daemon=True).start()
        print('starting')
    
        while True:
            print('i', i)
            if i %5 == 0:
                e.set()
            if i ==12:
                exit(0)
            i+=1
    
    start_generating()