Python 3 - Valueerror: Not Enough Values to Unpack (Expected 3, Got 2)

Python 3 - Valueerror: Not Enough Values to Unpack (Expected 3, Got 2)

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)
3

5 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()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Chloe Bennett
Author

Chloe Bennett

Chloe Bennett explores the intersection of pop culture, streaming entertainment, digital trends, and contemporary lifestyle. Her weekly commentary reaches thousands of culture enthusiasts.