To prevent SQL injection you should never use automatic casting of tuple to strings (what you are currently doing), or manually join a list of values before passing it to the driver.
You are currently making use of the fact that a tuple cast to string yields reasonable results:
str((1, 2))
# '(1, 2)'
but as you have noticed, single element tuples yield syntax errors:
str((1, ))
# '(1,)'
Some have suggested to concatenate the list manually:
','.join((1, 2))
# '1,2'
which would also work for single element tuples:
','.join((1,))
# '1'
however this opens the door to SQL injections, as the comma is in fact a control statement for MySQL, not just a value. So if somebody was able to sneak control statements in your list, they could inject code:
','.join((1,'1) OR 1=1 --'))
# '1,1) OR 1=1 --'
To be safe against such attacks you should prepare a query with exactly as many placeholders as elements in your list of id's:
doorbot_ids = [1, 2]
query = "SELECT id FROM dings_archive WHERE doorbot_id IN ({});".format(','.join(['%s'] * len(doorbot_ids)))
This returns a new query with exactly as many placeholders as required:
'SELECT id FROM dings_archive WHERE doorbot_id IN (%s,%s);'
and each placeholder is then filled with a value:
query = cursor.execute(query, doorbot_ids)