0

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:

debugger picture

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()
2
  • 2
    Well, for starters, you have a bare return on your if not row[0] and not row[1]: Commented Jun 11, 2018 at 19:01
  • 2
    As for the bit about needing to append a copy - that's not relevant in your case, because you're building a new entry every time. What'll cause surprising bugs is if you create a list of multiple references to the same object, EG some_list = [{}] * 10 or some_dict = {}; some_list = []; for i in range(10): some_list.append(some_dict). Commented Jun 11, 2018 at 19:04

1 Answer 1

3

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
Sign up to request clarification or add additional context in comments.

2 Comments

holy cow I can't (read: absolutely can) believe it was that simple.
@JaredT happens to the best of us :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.