I want to run multiple threads in python after I input anthing from the keyboard and I am getting this error - Exception in thread Thread-4:
import threading
import os
import cv2
def task():
user_input = input()
print(user_input)
print("Task assigned to thread: {}".format(threading.current_thread().name))
print("ID of process running task : {}".format(os.getpid()))
print("Thread started now")
if __name__ == "__main__":
for i in range(1, 5):
# Instantiates the thread
t = threading.Thread(target=task, args=(i,))
t.start()
t.join()
You should post the whole traceback. Here is what I get in all 4 threads:
Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Python38\lib\threading.py", line 932, in _bootstrap_inner
self.run()
File "C:Python38\lib\threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
TypeError: task() takes 0 positional arguments but 1 was given
It says the function task()
was passed an argument when it didn't require any, so don't pass an argument when creating the thread:
t = threading.Thread(target=task, args=())
or make task()
take an argument:
def task(i):
Asking for input in the thread doesn't really make sense either. No prompting and you won't know which thread is taking input.
Since using threading
and not multiprocessing
module, os.getpid()
is going to return the same value in all threads.
Also, if you start and join the thread in the same loop, you aren't getting any parallelism. Start all the threads in one loop, then join (wait for completion) in another loop.
Here's a solution that demonstrates parallelism:
import threading
import os
import time
def task(i):
print(f'Task#{i} started in {threading.current_thread().name}')
time.sleep(5) # do some "work"
print(f'Task#{i} done')
threads = [threading.Thread(target=task,args=(i,)) for i in range(1,5)]
print(f'Start: {time.ctime()}')
for t in threads:
t.start()
for t in threads:
t.join()
print(f'End: {time.ctime()}')
Output (note start and end times are 5 seconds apart):
Start: Sat Feb 15 16:22:59 2020
Task#1 started in Thread-1
Task#2 started in Thread-2
Task#3 started in Thread-3
Task#4 started in Thread-4
Task#1 done
Task#2 done
Task#4 done
Task#3 done
End: Sat Feb 15 16:23:04 2020
A final note: A process can only run Python code in one thread at a time due to CPython's global interpreter lock (GIL) implementation, so the threading
module won't save time for Python-intensive work, but is useful when Python is waiting on I/O or calling into native C modules that release the GIL. The multiprocessing
module can be used to create multiple Python processes that aren't limited by the GIL, but has longer process initialization time and arguments are passed through inter-process methods.
import multiprocessing as mp
import os
import time
def task(i):
print(f'Task#{i} started in {mp.current_process().name}')
time.sleep(5)
print(f'Task#{i} done')
if __name__ == '__main__':
processes = [mp.Process(target=task,args=(i,)) for i in range(1,5)]
print(f'Start: {time.ctime()}')
for p in processes:
p.start()
for p in processes:
p.join()
print(f'End: {time.ctime()}')
Output:
Start: Sat Feb 15 16:32:26 2020
Task#4 started in Process-4
Task#3 started in Process-3
Task#1 started in Process-1
Task#2 started in Process-2
Task#1 done
Task#4 done
Task#3 done
Task#2 done
End: Sat Feb 15 16:32:31 2020