Help Needed With Ex 41 oop_test.py - ValueError

Thanks in advance - I am hoping someone can help me with LPHW3 Ex 41 oop_test.py. I am unable to debug this code. I receive the following error after copying and pasting the code from the book and then trying to run it:

Traceback (most recent call last):
File “oop_test.py”, line 81, in
question, answer = convert(snippet, phrase)
ValueError: not enough values to unpack (expected 2, got 0)
PS C:\Users\sinua\OneDrive\Documents\Data_Science_Coding\python_hardway_3>

This is the code I am running which is exactly the same as in the book:

import random
from urllib.request import urlopen
import sys

WORD_URL = "http://learncodethehardway.org/words.txt"
WORDS = []

PHRASES = {
        "class %%%(%%%):":
            "Make a class named %%% that is-a %%%.",
        "class %%%(object):\n\tdef __init__(self, ***)" :
            "class %%% has-a __init__ that takes self and *** params.",
        "class %%%(object):\n\tdef ***(self, @@@)":
            "class %%% has-a function *** that takes self and @@@ params.",
        "*** = %%%()":
            "Set *** to an instance of class %%%.",
        "***.***(@@@)":
            "From *** get the *** function, call it with params self, @@@.",
        "***.*** = '***'":
            "From *** get the *** attribute and set it to '***'."
}

# do they want to drill phrases first
if len(sys.argv) == 2 and sys.argv[1] == "english":
    PHRASE_FIRST = True
else:
    PHRASE_FIRST = False

# load up the words from the website
for word in urlopen(WORD_URL).readlines():
    WORDS.append(str(word.strip(), encoding="utf-8"))


def convert(snippet, phrase):
    class_names = [w.capitalize() for w in
                  random.sample(WORDS, snippet.count("%%%"))]
    other_names = random.sample(WORDS, snippet.count("***"))
    results = []
    param_names = []

    for i in range(0, snippet.count("@@@")):
        param_count = random.randint(1,3)
        param_names.append(', '.join(
            random.sample(WORDS, param_count)))

    for sentence in snippet, phrase:
        result = sentence[:]

# fake class names
    for word in class_names:
        result = result.replace("%%%", word, 1)

# fake other names
    for word in other_names:
        result = result.replace("***", word, 1)

# fake parameter lists
    for word in param_names:
        result = result.replace("@@@", word, 1)

        results.append(result)

    return results

# keep going until they hit CTRL-D
try:
    while True:  
        snippets = list(PHRASES.keys())
        
        random.shuffle(snippets)

        for snippet in snippets:
           phrase = PHRASES[snippet]
           question, answer = convert(snippet, phrase)
           if PHRASE_FIRST:
               question, answer = answer, question

           print(question)
           input("> ")
           print(f"ANSWER: {answer}\n\n")
except EOFError:
    print("\nBye")

Your file is actually very different, and it’s all about the spacing. Remember that python uses indentation to figure out where code belongs, so yours is off in that regard. It can be difficult to see it, so do this:

  1. Get my version of the file here http://learnpythonthehardway.org/python3/python/ex41.py
  2. Use either this online tool https://wtools.io/check-difference-compare-merge or use the command line tool diff ex41_mine.py ex41_zeds.py to see the difference.
  3. Your text editor also most likely will have this diff tool so check the docs for it.
  4. Go through each line that’s shown as different and make it exactly the same.

Or, you can just use my version of the file.

Yes, my version was indeed VERY different and now has been fixed. Thank you for helping and sharing the tools for identifying the differences. This reinforced the importance of developing the skill to notice details in code,which you emphasize in the book and videos. Thanks again!

The thing to remember is you have to always assume you’re wrong. That’s really difficult for most people because they’re used to trusting their brain and assuming it’s telling them the truth. Programming (and actually painting) shows you that, nope, your brain lies to you constantly, usually be summarizing details as it thinks they’re not important. The number of spaces at the the beginning of a line of code is a good example of something your brain just skips over as pointless, but it’s very important.

Another example is how you probably didn’t catch that I typed “the” twice in that last paragraph.

3 Likes

I have another problem with this excercise:
I don’t get what
try-except part do…
When I run my program (or the orginal, cause I also tryied to pastle orginal one) and I want to exit it, I should press Ctrl-D to stope it, am I right? It doesnt work. I can stop running it using Ctrl-c, but it shows error, not Bye message… I When I remoed this try-except part from the code i worked exactly the same…
So my question is, what this try-except part is saying (maybe I misunderstood something) and if it is put there to close the program, how to do that, to see this “Bye” message :slight_smile:
Thanks in advance for help!

What’s the error message @Ola ?

Crtl-C is the default ‘get me out of this program’ command. It’s not the program completing so there’s a bug somewhere in your code.

Perhaps share it.

A try/except works like this:

try:
   # attempt something
except:
   # if that fails do this

Whenever the code under the try: has an exception Python will jump to the except: part and run that code instead. Think of this like an “abort spot”.

You can read more here:

Thank you for your responces!
This code has to be correct, I downloaded the Zed Show version to be sure about it.

The massage was:

Traceback (most recent call last):
File “ex41_Z.py”, line 81, in
input("> ")
KeyboardInterrupt

probably I shouldn’t call it error. Sorry, I’m just starting my adventure with programming (also my first time in any kind of forum!)

After your answers and information from docs.python.org I understood what this try/except is for.
Unfortunatly I still don’t understand why it is necessary to put this try/ except in this code…

Unfortunatly I still don’t understand why it is necessary to put this tr/ except in this code…

What action may cause this EOFError and printing of this “Bye!” information?
( Maybe the question should be what are the End of File conditions for this code?)

What should the user do to stop this program running?

I this example should show you:

>>> try:
...   input()
... except:
...   print "BOOM"
...
^DBOOM
>>>

I’m waiting for input then hitting ctrl-d, which causes an EOF.

Thanks again!
So after your example I ensured, that it should work exactly as I understood, but it still didn’t in my case.
So I started searching for the reason and I got it!
I have Windows and instead of pressing ^D I have to hit ^Z (I didn’t know about it)
Now everything works also in ex41!

Yes! I forgot about Windows using ^Z. That’s how you do it.