I have a problem with my Python 3 program. I use Mac OS X. This code is running properly.
# -*- coding: utf-8 -*- #! python3 # sendDuesReminders.py - Sends emails based on payment status in spreadsheet. import openpyxl, smtplib, sys # Open the spreadsheet and get the latest dues status. wb = openpyxl.load_workbook('duesRecords.xlsx') sheet = wb.get_sheet_by_name('Sheet1') lastCol = sheet.max_column latestMonth = sheet.cell(row=1, column=lastCol).value # Check each member's payment status. unpaidMembers = {} for r in range(2, sheet.max_row + 1): payment = sheet.cell(row=r, column=lastCol).value if payment != 'zaplacone': name = sheet.cell(row=r, column=2).value lastname = sheet.cell(row=r, column=3).value email = sheet.cell(row=r, column=4).value unpaidMembers[name] = email # Log in to email account. smtpObj = smtplib.SMTP_SSL('smtp.gmail.com', 465) smtpObj.ehlo() smtpObj.login('', '1234') # Send out reminder emails. for name, email in unpaidMembers.items() body = "Subject: %s - przypomnienie o platnosci raty za treningi GIT Parkour. " \ "\n\nPrzypominamy o uregulowaniu wplaty za uczestnictwo: %s w treningach GIT Parkour w ." \ "\n\nRecords show that you have not paid dues for %s. Please make " \ "this payment as soon as possible."%(latestMonth, name, latestMonth) print('Sending email to %s...' % email) sendmailStatus = smtpObj.sendmail('', email, body) if sendmailStatus != {}: print('There was a problem sending email to %s: %s' % (email, sendmailStatus)) smtpObj.quit()enter code here Problems starts when I am trying to add next value to the for loop.
# Send out reminder emails. for name, lastname, email in unpaidMembers.items() body = "Subject: %s - przypomnienie o platnosci raty za treningi GIT Parkour. " \ "\n\nPrzypominamy o uregulowaniu wplaty za uczestnictwo: %s %s w treningach GIT Parkour w ." \ "\n\nRecords show that you have not paid dues for %s. Please make " \ "this payment as soon as possible."%(latestMonth, name, lastname, latestMonth) print('Sending email to %s...' % email) sendmailStatus = smtpObj.sendmail('', email, body) Terminal shows error:
Traceback (most recent call last): File "sendDuesEmailReminder.py", line 44, in <module> for name, email, lastname in unpaidMembers.items(): ValueError: not enough values to unpack (expected 3, got 2) 35 Answers
You probably want to assign the lastname you are reading out here
lastname = sheet.cell(row=r, column=3).value to something; currently the program just forgets it
you could do that two lines after, like so
unpaidMembers[name] = lastname, email your program will still crash at the same place, because .items() still won't give you 3-tuples but rather something that has this structure: (name, (lastname, email))
good news is, python can handle this
for name, (lastname, email) in unpaidMembers.items(): etc.
1. First should understand the error meaning
Error not enough values to unpack (expected 3, got 2) means:
a 2 part tuple, but assign to 3 values
and I have written demo code to show for you:
#!/usr/bin/python # -*- coding: utf-8 -*- # Function: Showing how to understand ValueError 'not enough values to unpack (expected 3, got 2)' # Author: Crifan Li # Update: 20191212 def notEnoughUnpack(): """Showing how to understand python error `not enough values to unpack (expected 3, got 2)`""" # a dict, which single key's value is two part tuple valueIsTwoPartTupleDict = { "name1": ("lastname1", "email1"), "name2": ("lastname2", "email2"), } # Test case 1: got value from key gotLastname, gotEmail = valueIsTwoPartTupleDict["name1"] # OK print("gotLastname=%s, gotEmail=%s" % (gotLastname, gotEmail)) # gotLastname, gotEmail, gotOtherSomeValue = valueIsTwoPartTupleDict["name1"] # -> ValueError not enough values to unpack (expected 3, got 2) # Test case 2: got from dict.items() for eachKey, eachValues in valueIsTwoPartTupleDict.items(): print("eachKey=%s, eachValues=%s" % (eachKey, eachValues)) # same as following: # Background knowledge: each of dict.items() return (key, values) # here above eachValues is a tuple of two parts for eachKey, (eachValuePart1, eachValuePart2) in valueIsTwoPartTupleDict.items(): print("eachKey=%s, eachValuePart1=%s, eachValuePart2=%s" % (eachKey, eachValuePart1, eachValuePart2)) # but following: for eachKey, (eachValuePart1, eachValuePart2, eachValuePart3) in valueIsTwoPartTupleDict.items(): # will -> ValueError not enough values to unpack (expected 3, got 2) pass if __name__ == "__main__": notEnoughUnpack() using VSCode debug effect:

2. For your code
for name, email, lastname in unpaidMembers.items(): but error ValueError: not enough values to unpack (expected 3, got 2)
means each item(a tuple value) in unpaidMembers, only have 1 parts:email, which corresponding above code
unpaidMembers[name] = email so should change code to:
for name, email in unpaidMembers.items(): to avoid error.
But obviously you expect extra lastname, so should change your above code to
unpaidMembers[name] = (email, lastname) and better change to better syntax:
for name, (email, lastname) in unpaidMembers.items(): then everything is OK and clear.
In this line:
for name, email, lastname in unpaidMembers.items(): unpaidMembers.items() must have only two values per iteration.
Here is a small example to illustrate the problem:
This will work:
for alpha, beta, delta in [("first", "second", "third")]: print("alpha:", alpha, "beta:", beta, "delta:", delta) This will fail, and is what your code does:
for alpha, beta, delta in [("first", "second")]: print("alpha:", alpha, "beta:", beta, "delta:", delta) In this last example, what value in the list is assigned to delta? Nothing, There aren't enough values, and that is the problem.
Since unpaidMembers is a dictionary it always returns two values when called with .items() - (key, value). You may want to keep your data as a list of tuples [(name, email, lastname), (name, email, lastname)..].
ValueErrors :In Python, a value is the information that is stored within a certain object. To encounter a ValueError in Python means that is a problem with the content of the object you tried to assign the value to.
in your case name,lastname and email 3 parameters are there but unpaidmembers only contain 2 of them.
name, lastname, email in unpaidMembers.items() so you should refer data or your code might be
lastname, email in unpaidMembers.items() or name, email in unpaidMembers.items()