HOWTO · Python

ValueError: Python에서 압축을 풀 값이 충분하지 않음

ValueError: not enough values to unpack in Python은 사전 키를 반복하지만 값에도 액세스하거나, input 문에서 두 개의 입력을 받지만 두 개 미만의 값을 제공하거나, 예상 숫자에 더 적은 값을 할당하는 것과 같은 몇 가지 다른 시나리오에서 발생합니다. 값의 압축을 풀기에 값이 충분하지 않아 ValueError가 발생합니다.

이 페이지의 내용

Python은 할당문이나 반복문 헤더가 오른쪽 이터러블이 제공할 수 있는 것보다 더 많은 변수를 요구할 때마다 ValueError: not enough values to unpack를 발생시킵니다. 이 오류는 직접 할당에서, 너무 적은 필드로 분할된 입력에서, 그리고 각 쌍을 잘못된 개수의 이름으로 언패킹하는 사전 반복문에서 만나게 됩니다. 이 가이드는 메시지를 읽는 방법과 각 상황을 해결하는 방법을 보여줍니다. 실행 예제와 출력은 원문과 바이트 단위로 동일하게 유지되므로 입력 안내와 출력 문구는 영어로 표시됩니다.

Python에서 ValueError: not enough values to unpack가 발생하는 이유

언패킹은 튜플, 리스트, 문자열, 뷰 객체와 같은 이터러블의 항목을 그에 대응하는 이름 목록에 할당합니다. a, b, c = 3, 5에서 Python은 아무것도 할당하기 전에 양쪽의 개수를 셉니다. 왼쪽에는 이름 세 개, 오른쪽에는 값 두 개가 있습니다. 작성된 대상보다 적은 값이 도착했으므로 인터프리터는 expected 3, got 2처럼 두 개수를 함께 보고하는 메시지를 가진 ValueError를 발생시킵니다. 이 두 숫자가 진단의 핵심입니다. 첫 번째는 작성한 대상의 수이고, 두 번째는 이터러블이 실제로 생성한 값의 수입니다.

Python이 보고하는 메시지를 보려면 다음 예제를 실행해 보세요:

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

try:
    a, b, c = 3, 5
except ValueError as error:
    print("ValueError:", error)
ValueError: not enough values to unpack (expected 3, got 2)

try/except가 없으면 프로그램은 할당 줄에서 멈춥니다. 대상 목록보다 짧은 모든 이터러블에서 같은 불일치가 나타납니다. a, b, d, e = [1, 2, 3]은 항목이 세 개인 리스트에서 네 개의 이름을 요구하고, a, b, c = 2는 정수 하나에서 세 개의 이름을 요구하므로 Python이 전혀 언패킹할 수 없습니다.

할당과 입력에서 언패킹 오류 수정하기

가장 간단한 해결 방법은 양쪽을 일치시키는 것입니다. 왼쪽의 이름 개수는 오른쪽이 제공할 수 있는 값의 개수와 같아야 합니다. 값이 input()에서 올 때는 input()이 항상 문자열을 반환한다는 점을 기억하세요. 따라서 split()이 할당이 실제로 받는 필드 수를 결정합니다. 아래 프로그램은 쉼표로 구분된 숫자 세 개를 요청하고 세 개를 받으므로 언패킹이 성공하고 곱셈이 실행됩니다. 다음 예제를 실행해 보세요:

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

import sys
from io import StringIO

# Simulate typing "2,2,2" at the prompt.
sys.stdin = StringIO("2,2,2\n")

x, y, z = input("Enter three numbers to multiply: ").split(",")
product = int(x) * int(y) * int(z)
print("The product of x, y, and z is:", product)
Enter three numbers to multiply: The product of x, y, and z is: 8

sys.stdin 줄은 사용자가 2,2,2를 입력하는 상황을 대신합니다. 실제 프로그램에서는 평소처럼 input()을 호출하고, 키보드 앞의 사용자가 몇 개의 필드가 도착할지 결정합니다. 대상이 필요로 하는 것보다 적은 필드를 입력하면 분할된 리스트가 너무 짧아져 같은 ValueError가 나타납니다:

import sys
from io import StringIO

# Simulate typing "1,2" at the prompt.
sys.stdin = StringIO("1,2\n")

try:
    x, y, z = input("Enter values for x, y and z: ").split(",")
except ValueError as error:
    print("ValueError:", error)
Enter values for x, y and z: ValueError: not enough values to unpack (expected 3, got 2)

오른쪽의 길이가 실제로 달라질 수 있다면 별표가 붙은 대상이 남는 항목을 흡수합니다. first, *rest = [1, 2, 3]은 first를 1에, rest를 [2, 3]에 바인딩합니다. 별표는 항목이 더 많은 것이 문제일 때만 도움이 됩니다. 값이 너무 적게 도착할 때는 개수를 맞추거나 먼저 입력을 검증하세요.

.items()로 사전 언패킹 오류 수정하기

사전은 키-값 쌍을 저장합니다. 사전 자체를 반복하면 키만 얻고, .items()는 각 쌍이 정확히 두 개의 값을 가지는 (key, value) 쌍의 뷰를 반환합니다. 다음 세 가지 표준 뷰를 확인할 수 있습니다:

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

student = {"name": "Zeeshan Afridi", "degree": "BSSE", "section": "A"}

print("Keys:", student.keys())
print("Values:", student.values())
print("Items:", student.items())
Keys: dict_keys(['name', 'degree', 'section'])
Values: dict_values(['Zeeshan Afridi', 'BSSE', 'A'])
Items: dict_items([('name', 'Zeeshan Afridi'), ('degree', 'BSSE'), ('section', 'A')])

.items()의 모든 요소는 두 개의 값을 가진 쌍이므로, 대상이 세 개인 반복문 헤더는 첫 번째 반복에서 실패합니다. 개수를 정하는 것은 메서드가 아니라 값을 제공하는 쌍입니다:

student = {"name": "Zeeshan Afridi", "degree": "BSSE", "section": "A"}

try:
    for k, v, l in student.items():
        print(k, v, l)
except ValueError as error:
    print("ValueError:", error)
ValueError: not enough values to unpack (expected 3, got 2)

해결 방법은 각 쌍을 키용 이름 하나와 값용 이름 하나, 총 두 개의 이름으로 언패킹하는 것입니다:

student = {"name": "Zeeshan Afridi", "degree": "BSSE", "section": "A"}

for key, value in student.items():
    print("Key:", key)
    print("Value:", value)
Key: name
Value: Zeeshan Afridi
Key: degree
Value: BSSE
Key: section
Value: A

키만 필요하면 for key in student:처럼 사전을 직접 반복하고, 값만 필요하면 .values()를 사용하세요. 키만 반복하는 루프에서 언패킹하지 않도록 주의하세요. for k, v in student:는 각 키 문자열 자체를 언패킹하려고 하므로, 여러 문자로 된 키는 too many values to unpack 오류로 실패합니다.

입력을 검증하고 언패킹 오류 처리하기

두 가지 습관이 이 오류가 사용자에게 닿지 않게 합니다. 첫째, 언패킹하기 전에 필드 수를 세세요. split()은 리스트를 제공하고 len()은 할당하려는 이름 수와 일치하는지 알려주므로, 명확한 안내 문구로 데이터를 다시 요청할 수 있습니다:

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

import sys
from io import StringIO

# Simulate typing "1,2" at the prompt.
sys.stdin = StringIO("1,2\n")

parts = input("Enter three numbers to multiply: ").split(",")

if len(parts) != 3:
    print("Please enter exactly three numbers separated by commas.")
else:
    x, y, z = (int(part) for part in parts)
    print("The product of x, y, and z is:", x * y * z)
Enter three numbers to multiply: Please enter exactly three numbers separated by commas.

둘째, 언패킹 및 변환 블록을 try/except로 감싸세요. Python 키워드는 일부 다른 언어에서 사용하는 try-catch 철자가 아니라 try와 except입니다. int()도 숫자가 아닌 필드에 대해 ValueError를 발생시키므로, 하나의 except 절이 짧은 필드 목록과 변환할 수 없는 값을 모두 처리합니다:

import sys
from io import StringIO

# Simulate typing "2,two,4" at the prompt.
sys.stdin = StringIO("2,two,4\n")

try:
    x, y, z = input("Enter three numbers to multiply: ").split(",")
    product = int(x) * int(y) * int(z)
    print("The product of x, y, and z is:", product)
except ValueError as error:
    print("Could not use that input:", error)
Enter three numbers to multiply: Could not use that input: invalid literal for int() with base 10: 'two'

예외를 잡으면 프로그램이 복구될 수 있지만 데이터가 수정되는 것은 아닙니다. 사용자에게 정확히 무엇을 입력해야 하는지 알려줄 수 있도록 길이 검사와 입력에 필요한 숫자 또는 형식 검사를 우선 적용하고, try/except는 언패킹 자체를 둘러싼 안전망으로 유지하세요.