GarennePb GarennePb - 1 month ago 6
Python Question

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 !

Answer

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.