0

I am trying to insert data received through serial into a mysql table using python 3, however, when I try to input my insert statement I get a "TypeError: not enough arguments for format string". Any help would be greatly appreciated!

I tried using ", (new_data)" instead of "% (new_data)" and got SQL syntax error. Also tried ".format(new_data)" which did not produce an error, but resulted in empty string fields or 0.00 float fields.

raw_data=ser.readline() #Fetch a line from the serial feed

new_data=raw_data.decode('ascii').rstrip()  #Remove extraneous control characters

new_data=(new_data, ) #Convert to a tuple

#Result
#("'2019-5-21 7:55:5',0,3.1,25.6,315,2.2,316,11.0,248,56.6,56.9,0.00,0.73,100375.50,4.37,0.83",)

#Now insert into the database
sql="INSERT INTO reports (rec_time, wnddir, wndspd, wndgust, wndgustdir, wndspdavg2m, wnddiravg2m, wndgustavg10M, wndgustdiravg10M, humidity, tempf, rain, raindly, pressure, battery, light) VALUES ('%s', '%d', '%f', '%f', '%d', '%f', '%d', '%f', '%d', '%f', '%f', '%f', '%f', '%f', '%f', '%f')" % (new_data)
cursor.execute(sql)

I am expecting a record to be written to the database, however, I get a "TypeError: not enough arguments for format string". There are 16 fields, 16 placeholders and 16 pieces of data. What am I doing incorrectly?

Barmar
  • 741,623
  • 53
  • 500
  • 612
RonW
  • 1
  • You have an extra `"` inside the `sql` string, before `'%d'`. – Barmar May 21 '19 at 21:35
  • That should be causing a Python syntax error, not a type error. Was it a copy/paste error? – Barmar May 21 '19 at 21:36
  • Yes, it was a copy and paste error. Sorry. – RonW May 21 '19 at 21:38
  • `new_data` is a tuple with 1 element in it, the string that was returned by `raw_data.decode('ascii').rstrip()`. Where do the 15 other values come from? – Barmar May 21 '19 at 21:38
  • The quotes and commas inside the string don't cause them to become separate elements of the tuple. It's still just a single string, which you need to parse. It looks like this is a CSV file, perhaps you should use the `csv` module? – Barmar May 21 '19 at 21:40
  • Given that comment, my error would be in creating the tuple from the raw string of data? I thought I was creating tuple with 16 elements based on comma delimiters. – RonW May 21 '19 at 21:41
  • No. Variables are never automatically parsed as if the contents are part of the source code. – Barmar May 21 '19 at 21:42
  • See https://stackoverflow.com/questions/3305926/python-csv-string-to-array for how to parse a CSV row from a string. – Barmar May 21 '19 at 21:44
  • Thank you! I will! – RonW May 21 '19 at 21:45
  • You should also avoid using string formatting to create SQL. Put placeholders in the string and let `cursor.execute()` substitute them. This prevents SQL-injection. – Barmar May 21 '19 at 21:46

1 Answers1

0

There are 16 fields, 16 placeholders and 16 pieces of data.

new_data=(new_data, ) #Convert to a tuple

No, there's just a 1-tuple, rather than a 16-tuple.

Consider this example:

>>> 6,
(6,)

It creates a 1-tuple, containing the single element six. In your case, you created a 1-tuple containing a string, one which has many characters, including commas. But it's still a 1-tuple, so .format() is still looking for 15 more args.

Use the csv module to iterate over your input file, and you'll be much happier.

J_H
  • 17,926
  • 4
  • 24
  • 44