pythonmultithreadingdynamic-list

Issues with thread and dynamic list in python


I will try to be clear, hoping everyobdy will understand even if it will not be easy for me. I'm a beginner in coding in python so every help will be nice ! I've got those librairies import : requests and threading. I'm trying to send in parrallel several urls to reduce the sending time of data. I used a dynamic list to stack all urls and then used requests.post to send them.

l=[]
        if ALARM&1:
            alarmType="Break Alarm"
            AlarmNumber = 1
            sendAlarm(alarmType, AlarmNumber)
            print alarmType
        else:
            s = "https://..." #the url works 
            l.append(threading.Thread(target=requests.post, args=(s)))
        if ALARM&2:
            alarmType=0
        if ALARM&4:
            alarmType="Limit Switch"
            AlarmNumber = 2
            sendAlarm(alarmType, AlarmNumber)
            print alarmType
        else:
            s="https://..." 
            l.append(threading.Thread(target=requests.post, args=(s)))

        for t in l:
            t.start()
        for t in l:
            t.join()

The error that I got is :

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 763, in run
    self.__target(*self.__args, **self.__kwargs)
TypeError: post() takes at most 3 arguments (110 given)

And same thing for Thread-2, I asked around me but we can't find a solution. If someone have an idea ? Thanks !


Solution

  • From the docs, args should be a tuple.

    class threading.Thread(group=None, target=None, name=None, args=(), kwargs={})

    args is the argument tuple for the target invocation. Defaults to ().

    You need to pass args a tuple with the url as the first (and only) element:

    l.append(threading.Thread(target=requests.post, args=(s,)))
    

    The seemingly useless comma here is what makes Pyhton interpret (s,) as a set and not just a string surrounded by unneeded parenthesis.

    Failing to do this, you're basically passing a string, and Thread iterates on it, passing post each letter as a separate argument, hence the error message:

    TypeError: post() takes at most 3 arguments (110 given)
    

    A string being interpreted as an iterator is a common pitfall. A function/method expects a list/set, and when provided a string like "https://...", it treats it like ['"', 'h', 't', 't', 'p', 's', ':', '/', '/',...].

    The root cause of the issue is anecdotal, somehow. What's interesting, here, is that although I knew about nothing of Thread when reading the question, the error message (TypeError: post() takes at most 3 arguments (110 given)) pointed me to the right direction right away.