0

While working with some code given to me by my professor to use in an assignment, I cannot change per instructions. I've been looking around and added closing around the initial write but is there to prevent modify the starter code?

The code came from:

Calling Code:

def run_menu():

    global CURRENT_TIME

    # Provide a minimal indication that the program has started.
    print(MINIMAL_HELP_STRING)

    # Get the first keystroke.
    c = readchar.readchar()

    # Endless loop responding to the user's last keystroke.
    # The loop breaks when the user hits the QUIT_MENU_KEY.
    while True:

        # Respond to the user's input.
        if c == FORWARD_KEY:

            # Advance the time, looping back around to the start.
            CURRENT_TIME += 1
            if CURRENT_TIME == len(NUMBERS_WAV):
                CURRENT_TIME = 0

            # Concatenate three audio files to generate the message.
            sound.combine_wav_files(TMP_FILE_WAV, YOU_SELECTED_WAV,
                                    NUMBERS_WAV[CURRENT_TIME], AM_WAV)

            # Play the concatenated file.
            sound.Play(TMP_FILE_WAV)

Function Code:

def combine_wav_files(out_file, *files):
    with wave.open(out_file, 'wb') as out:
        with wave.open(files[0], 'rb') as first_in:
            (nchannels, sampwidth, framerate, nframes, comptype, compname) =\
              first_in.getparams()
            out.setparams(first_in.getparams())
        for filename in files:
            with wave.open(filename, 'rb') as cur_in:
                if (cur_in.getnchannels() != nchannels or
                    cur_in.getsampwidth() != sampwidth or
                    cur_in.getframerate() != framerate or
                    cur_in.getcomptype() != comptype or
                    cur_in.getcompname() != compname):
                    raise Exception('Mismatched file parameters: ' + filename)
                out.writeframes(cur_in.readframes(cur_in.getnframes()))

Error Message:

Exception wave.Error: Error('# channels not specified',) in <bound method Wave_write.__del__ of <wave.Wave_write instance at 0x104029e60>> ignored
Traceback (most recent call last):
    File "sample_menu.py", line 144, in <module>
      main()
    File "sample_menu.py", line 25, in main
      run_menu()
    File "sample_menu.py", line 113, in run_menu
      NUMBERS_WAV[CURRENT_TIME], AM_WAV)
    File "/Users/jaredsmith/Desktop/443/P1 Starter Code 2017/sound.py", line 86, in combine_wav_files
      with wave.open(out_file, 'wb') as out:
AttributeError: Wave_write instance has no attribute '__exit__'

I put the fix under the imports and it works!

Fix (Update):

####
# From http://web.mit.edu/jgross/Public/21M.065/sound.py 9-24-2017    
####

def _trivial__enter__(self):
    return self
def _self_close__exit__(self, exc_type, exc_value, traceback):
    self.close()

wave.Wave_read.__exit__ = wave.Wave_write.__exit__ = _self_close__exit__
wave.Wave_read.__enter__ = wave.Wave_write.__enter__ = _trivial__enter__

4 Answers 4

2

You are using a Wave_write instance inside a with statement. For it to work properly, Wave_write must be a context manager, meaning it must implement both methods __enter__() and __exit__(). That is not the case here.

You must either add the __exit__ method to Wave_write, or remove the with statement and close the input manually (if needed). Example:

out = wave.open(out_file, 'wb'):
    [do_stuff]
out.close() # if Wave_write implements a closing method, use it. the with statement and __exit__() method would have handled that for you.

See https://docs.python.org/2/reference/compound_stmts.html#with and https://docs.python.org/2/library/contextlib.html

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! Helped me understand how to fix it
1

The with keyword in this line

with wave.open(out_file, 'wb') as out

implies that wave.open has been written as a context manager, but it hasn't. Take out the with and do this instead:

out = wave.open(out_file, 'wb')

Comments

1

If that code was given to you by your professor then he was using python3, where the object returned by wave.open() can be used as a context manager. You seem to be using python2, where that wasn't the case.

You should use the same version as your professor, otherwise you'll run into such problems all the time. So you should probably switch to python3.

Comments

0

for me the work around is to add below code as mentioned by JD Smith in the above thread (AttributeError: Wave_write instance has no attribute '__exit__'). this works for me. just add these lines of code below your import statement and it will work. make sure you add (import wave statement)

import wave

def _trivial__enter__(self):
    return self
def _self_close__exit__(self, exc_type, exc_value, traceback):
    self.close()

wave.Wave_read.__exit__ = wave.Wave_write.__exit__ = _self_close__exit__
wave.Wave_read.__enter__ = wave.Wave_write.__enter__ = _trivial__enter__

Comments

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.