Reputation: 103
According to my debugger and my 25-row test csv, the patient_appts
list contains 25 dicts as expected. I can't seem to figure out how that list becomes None
between the local variable, return statement, and main function.
I've read in a few places that you need to make a copy instead of appending a reference, which I've done, as far as I know, using patient_appts.append(entry.copy())
Sorry if the code is kind of a trainwreck, I'm pretty new to this and trying to automate some work - for instance I'm pretty sure I shouldn't be manually creating json formatting for my data, but that is out of scope for this question.
I've tried instantiating the list globally and not within the function, globally and declared global within function, instantiating list just after with ed as ed_file:
; they all seem to produce the same result (at print(len(appointments))
):
Exception has occurred. TypeError, object of type 'NoneType' has no len()
Debugger clearly showing the dicts within the list before making it to return
:
import csv
from datetime import datetime, timedelta
from validate_email import validate_email
from fieldMap import fieldMap
record_count = 0
valid_email_count = 0
def run_CSV(ed):
with ed as ed_file:
global record_count
global valid_email_count
patient_appts = []
header_row = True
ed_reader = csv.reader(ed_file, delimiter=',', quotechar='"')
for row in ed_reader:
if not row[0] and not row[1]:
print('\n%i records written to csv' % record_count
+ '\n%i valid emails found' % valid_email_count)
return
elif header_row:
headers = list(row)
i_fname = headers.index(fieldMap['FirstName'])
i_mname = headers.index(fieldMap['MiddleName'])
i_lname = headers.index(fieldMap['LastName'])
i_email = headers.index(fieldMap['Email'])
i_start = headers.index(fieldMap['StartTime'])
i_end = headers.index(fieldMap['EndTime'])
i_location = headers.index(fieldMap['Location'])
i_type = headers.index(fieldMap['Type'])
i_appt_id = headers.index(fieldMap['ApptID'])
header_row = False
else:
duration = getDuration(row[i_start], row[i_end])
start_time = row[i_start]
end_time = row[i_end]
valid_email = validate_email(row[i_email])
if valid_email:
valid_email_count += 1
record_count += 1
entry = {
'ApptID': row[i_appt_id],
'Data': {
'Patient': {
'FirstName': row[i_fname],
'MiddleName': row[i_mname],
'LastName': row[i_lname],
'Email': row[i_email],
'Valid Email': valid_email,
'Appointment': {
'Type': row[i_type],
'Location': row[i_location],
'StartTime': start_time,
'EndTime': end_time,
'Duration': duration
}
}
}
}
patient_appts.append(entry.copy())
return patient_appts
def getDuration(start_time, end_time):
fmt = '%I:%M %p'
tdelta = datetime.strptime(
end_time, fmt) - datetime.strptime(start_time, fmt)
duration = str(tdelta).split(':')[1]
return duration
def main():
appointments = run_CSV(open(input('Enter full CSV Path:\n'), newline='\n'))
print(len(appointments))
if __name__ == '__main__':
main()
Upvotes: 0
Views: 88
Reputation: 11922
You have a random return
statement within the run_CSV
function, and when you hit that your functions returns nothing - None
When your main
funcion tries to do len
on that None
you will get that error. Since this is part of a loop i'm guessing you meant to use break
there and not return
It should look like this:
for row in ed_reader:
if not row[0] and not row[1]:
print('\n%i records written to csv' % record_count
+ '\n%i valid emails found' % valid_email_count)
break # formerly "return" was here
Upvotes: 3