'Is it not allowed to make a new thread with the same name even though I already kill one?

I made a gui that perform two different jobs with two different intervals with start and stop feature. The goal is to make 2 threads on and off as a user wants. The first start and kill try is just fine, but when I try to make new threads after terminating them it spews an error

Given the following code:

import PySimpleGUI as sg
import threading
from binance import Client
import time


def make_window(theme=None):
    sg.theme("DarkBlack")

    column = [
        [ sg.Button('do_stuff1_start'), sg.Button("do_stuff1_kill") ],
        [ sg.Button('do_stuff2_start'), sg.Button("do_stuff2_kill") ] ]
    layout = [
        [ sg.T('DCA', font='_ 18', justification='c', expand_x=True) ],
        [ sg.Col(column) ] ]

    window = sg.Window('DCA', layout, finalize=True,
                       keep_on_top=True)
    return window


def do_stuff1(stop_event, arg):
    while not stop_event.is_set():
        print("do stuff 1")
        time.sleep(5)
    print("stopped do_stuff1")


def do_stuff2(stop_event, arg):
    while not stop_event.is_set():
        print("do stuff 2")
        time.sleep(10)
    print("stopped do_stuff2")


if __name__ == '__main__':

    api_key = "zzz"
    api_secret = "zzz"
    client = Client(api_key, api_secret)

    window = make_window()
    window.finalize()

    while True:
        event, values = window.read()
        if event == sg.WIN_CLOSED or event == 'Exit':
            break

        elif event == 'do_stuff1_start':
            pill2kill1 = threading.Event()
            do_stuff1 = threading.Thread(target=do_stuff1, args=(pill2kill1, "task1"))
            do_stuff1.start()

        elif event == 'do_stuff2_start':
            pill2kill2 = threading.Event()
            do_stuff2 = threading.Thread(target=do_stuff2, args=(pill2kill2, "task2"))
            do_stuff2.start()

        elif event == 'do_stuff1_kill':
            pill2kill1.set()
            do_stuff1.join()
            print('killed do_stuff1')

        elif event == 'do_stuff2_kill':
            pill2kill2.set()
            do_stuff2.join()
            print('killed do_stuff2')


I clicked do_stuff1_start, do_stuff2_start buttons in my gui and checked them working properly. Then, I clicked do_stuff1_kill, do_stuff2_kill buttons, also, they worked fine. The problem is when I click the start buttons again, it spews the below

Exception in thread Thread-3: Traceback (most recent call last): File "C:\Users\asd93\AppData\Local\Programs\Python\Python39\lib\threading.py", line 973, in _bootstrap_inner self.run() File "C:\Users\asd93\AppData\Local\Programs\Python\Python39\lib\threading.py", line 910, in run self._target(*self._args, **self._kwargs) TypeError: 'Thread' object is not callable

I thought I already completely kill my threads and there is no problem to make them again since there is no living thread with the same name and it is not like "restart" a thread but just making new one on a blank slate.

Am I missing something?



Solution 1:[1]

The PROBLEM is that you have given your thread variable the same name as your function. After you create the first thread, the do_stuff1 function is deleted. (OK, it's not literally deleted, because a reference still exists, but you can no longer access it.) That name now refers to a thread object, and will do so forevermore. Use a different name. For example:

do_stuff1_thread = threading.Thread( target=do_stuff1, args=(pill2kill, "task1"))

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tim Roberts