0

I started to use the threading library recently because I need to make my software faster but unfortunately I can't. below an example about what I wanna do:

from threading import Thread

# in my PC, it takes around 30 seconds to complete the task:
def do_something(string):
    a=string
    for n in range(1000000000):
       a+=a+a 
    return {"a":"aa", "b":"bb", "c":"cc"}

ls_a, ls_b, ls_c = [], [], []
ls_strings=["ciao", "hello", "hola"]

for key in ls_strings:
    t=Thread(target=do_something, args=(key,))
    t.start()
    dic=t.join()
    
    ls_a.append(dic["a"]) # <--- TypeError: 'NoneType' object is not subscriptable
    ls_b.append(dic["b"])
    ls_c.append(dic["c"])

print(ls_a)
print(ls_b)
print(ls_c)

this code doesn't work, it returns an exception when Python starts to read the line "ls_a.append(dic["a"])":

TypeError: 'NoneType' object is not subscriptable

there is this error because the instruction "dic=t.join()" returns "None" and I really don't understand why (I expected to receive "a" and not "None"). why does't the method "join" work? how can I fix my code? can you guys help me to understand?

TurboC
  • 777
  • 1
  • 5
  • 19
  • `join` doesn't return anything (or rather, it always returns `None`). Why are you trying to use it like this? Instead, use a threadsafe container or a thread pool if you need to take results out of the function. – Carcigenicate Sep 28 '22 at 23:09
  • 1
    If you launch a thread and immediately `join` it, there was no reason to launch the thread in the first place (the thread that launched and joined it could have just done the work itself with less overhead). – ShadowRanger Sep 28 '22 at 23:11
  • Also note: CPU bound threads (that don't use third-party libraries that release the GIL while doing the work) are *useless* for improving speed on CPython, the GIL means only one thread can be executing Python bytecode at a time. Your example function is the worst possible thing for threading in CPython. – ShadowRanger Sep 28 '22 at 23:14
  • guys, I'm not an expert with multithreaing, what I want to do is run "do_something" function for more strings (in my example "ciao", "hello" and "hola") at the same time. can you show me how to do that, and at the same time advice me what are the right libraries and methods to study? I'm a little bit confused with the documentation online. – TurboC Sep 28 '22 at 23:17
  • @TurboC Like I said, I'd use a thread pool. I'd use [this](https://docs.python.org/3/library/concurrent.futures.html). Instead of your `for` loop that creates threads, create a pool of threads, then use `map` on the pool. – Carcigenicate Sep 29 '22 at 00:02

1 Answers1

0

what I want to do is run "do_something" function for more strings (in my example "ciao", "hello" and "hola") at the same time.

The trick in that case is, to not join any of them until all of them have been started. Use two loops instead of just one:

threads = []
for key in ls_strings:
    t=Thread(target=do_something, args=(key,))
    t.start()
    threads.append(t)

# optionally, do something else here while the threads run.

for t in threads:
    t.join()

Note: this does not solve your problem of how to "return" a value from a thread. There's lots of questions already answered on this site that tell you how to do that (e.g., How to get the return value from a thread in Python?)

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57