Passing arguments to threading.Thread

16,355

args is a sequence of arguments to pass; if you want to pass in a list as the sole positional argument, you need to pass args=(my_list,) to make it a one-tuple containing the list (or mostly equivalently, args=[my_list]).

It needs to be a sequence of arguments, even when only one argument is passed, precisely to avoid the ambiguity you created. If scr_runner took three arguments, two with default values, and my_list had a length of 3, did you mean to pass the three elements as the three arguments, or should my_list be the first argument, and the other two remain the default?

Share:
16,355
Adrian Keister
Author by

Adrian Keister

Mathematical physicist working as a data scientist for Mayo Clinic. I am an evangelical Christian first, Reformed second, Presbyterian (Presbyterian Church in America) third. Happily married with four children, the youngest of whom is deaf.

Updated on June 04, 2022

Comments

  • Adrian Keister
    Adrian Keister about 2 years

    I'm using Python 3 on Windows. I am using threading.Thread to run a function dynamically, and I may call it with or without arguments. I'm setting up a list of things, the first item of which is a string defining a path. The other arguments will be later things in the list. So, args might equal ['C:\SomePath'] or it might equal ['C:\SomePath', 'First Argument', 'Second Argument']. My call looks like this:

    my_script = threading.Thread(target=scr_runner, args=q_data.data)
    my_script.start()
    

    The problem is that somewhere in the process of calling the threading.Thread and/or start function, the arguments are losing their list characteristic (isinstance(q_data.data, str)=False), but inside the scr_runner function, which takes the script_to_run_data argument, isinstance(script_to_run_data, str)=True.

    I need this argument to remain a list throughout. How can I do that?

    I read in the docs that the threading.Thread function is expecting a tuple. Is there some issue with converting something like ['C:\SomePath'] to a tuple, where it becomes a string?

    Thanks in advance for your time!

    Here is a MWE:

    # coding=utf-8
    """ This code tests conversion to list in dynamic calling. """
    
    import threading
    
    
    def scr_runner(script_to_run_data: tuple) -> None:
        """ This is the function to call dynamically. """
        is_list = not isinstance(script_to_run_data, str)
        print("scr_runner arguments are a list: T/F. " + str(is_list))
    
    
    my_list=['C:\SomePath']
    is_list = not isinstance(my_list, str)
    print("About to run script with list argument: T/F. " + str(is_list))
    my_script = threading.Thread(target=scr_runner, args=my_list)
    my_script.start()
    

    Now, what's odd is that I get an error when I make my_list have more elements:

    # coding=utf-8
    """ This code tests conversion to list in dynamic calling. """
    
    import threading
    
    
    def scr_runner(script_to_run_data: tuple) -> None:
        """ This is the function to call dynamically. """
        is_list = not isinstance(script_to_run_data, str)
        print("scr_runner arguments are a list: T/F. " + str(is_list))
    
    
    my_list=['C:\SomePath', 'First Argument', 'Second Argument']
    is_list = not isinstance(my_list, str)
    print("About to run script with list argument: T/F. " + str(is_list))
    my_script = threading.Thread(target=scr_runner, args=my_list)
    my_script.start()
    

    produces the error:

    About to run script with list argument: T/F. True
    Exception in thread Thread-1:
    Traceback (most recent call last):
      File "C:\ProgramData\Anaconda3\lib\threading.py", line 916, in  
           _bootstrap_inner
        self.run()
      File "C:\ProgramData\Anaconda3\lib\threading.py", line 864, in run
        self._target(*self._args, **self._kwargs)
    TypeError: scr_runner() takes 1 positional argument but 3 were given