Without seeing more of the error data from the serial port, I can say that the most common reason you would see single numbers on lines (or even blank lines) is due to the non-synchronization between the Arduino program sending data to the port and your program trying to read that data. I'd wager if you print data after your data=ser.readline() and comment out the rest of the processing, you'd find lines like some of the following in the output:
252, 236, 218, 1136
251, 202, 215
2, 1353
199, 303, 200, 1000
259, 231, 245, 993
28
4, 144, 142, 1112
245, 199, 143, 1403
251, 19
2, 187, 1639
246, 235, 356, 1323
The reason for the data split across lines, or even blank lines, is that the program is trying to read data from the serial connection during or between writes. When this happens, the readline() gets what's available (even if partially/not written) and throws a \n on the end of what it found.
The fix for this is to ensure that the Arduino has finished sending data before we read, and that there is data there for us to read. A good way to handle this is with a generator that only yields lines to the main loop when they are complete (e.g. they end with a \r\n signifying the end of a write to the port).
def get_data():
ibuffer = "" # Buffer for raw data waiting to be processed
while True:
time.sleep(.1) # Best between .1 and 1
data = ser.read(4096) # May need to adjust read size
ibuffer += data # Concat data sets that were possibly split during reading
if '\r\n' in ibuffer: # If complete data set
line, ibuffer = ibuffer.split('\r\n', 1) # Split off first completed set
yield line.strip('\r\n') # Sanitize and Yield data
The yield makes this function a generator you can invoke to grab the next complete set of data while keeping any thing that was split by the read() in a buffer to await the next read() where the pieces of the data set can be concatenated. Think of yield like a return, but rather than passing a value and leaving the function/loop, it passes the value and waits for next() to be called where it will pick up where it left off for the next pass through the loop. With this function, the rest of your program will look something like this:
import serial, time, csv, decimal
port = '/dev/cu.usbserial-A401316V'
ser = serial.Serial(port , baudrate=57600, bytesize=8, parity=serial.PARITY_NONE, stopbits=1, timeout=2)
def get_data():
"""
The above function here
"""
ser_data = get_data()
while True:
data = ser_data.next().replace(' ','').split(',')
if len(data) > 0:
"""
data processing down here
"""
ser.close()
Depending on your set up, you may want to throw a conditional in get_data() to break, if the serial connection is lost for example, or a try/except around the data declaration.
It's worth noting that one thing I did change aside from the aforementioned is your ser.readline(eol) to a byte sized ser.read(4096). PySerial's readline() with eol is actually deprecated with the latest versions of Python.
Hopefully this helps; or if you have more problems, hopefully it at least gives you some ideas to get on the right track.