ValueError: too many values to unpack...

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • f0rd
    New Member
    • Mar 2010
    • 4

    ValueError: too many values to unpack...

    Hi everybody, I have a python script I developed for work, that organises sound samples and out puts them to a text file.

    Here is an example input file:
    Code:
    Sound001,15,6
    Sound002,15,6
    Sound003,30,3
    Sound004,30,3
    Sound005,30,3
    Sound006,60,6
    Sound007,60,6
    Sound008,60,6
    Where the first set of numbers after the comma is the duration of the sound in seconds, and the last number is the minimum amount of play time in seconds.

    Python 2.6.1 (r261:67515, Jul 7 2009, 23:51:51)
    [GCC 4.2.1 (Apple Inc. build 5646)] on darwin

    I get the following error:
    Code:
    Traceback (most recent call last):
      File "playlister.py", line 31, in <module>
        name, seconds_long, min_playtime_minutes = map(str.strip, line.split(','))
    ValueError: too many values to unpack
    And the last call is:

    Code:
    file = open(filename, 'r')
    
    lines = {}
    required_plays = {}
    
    time_to_play_all_required = 0
    
    playlist = []
    
    for line in file.readlines():
        name, seconds_long, min_playtime_minutes = map(str.strip, line.split(','))
        seconds_long = int(seconds_long)
        min_playtime_minutes = int(min_playtime_minutes)
        lines[name] = (seconds_long, min_playtime_minutes)
        time_to_play_all_required += min_playtime_minutes
        times_to_play = (min_playtime_minutes * 60) / seconds_long
        required_plays[name] = times_to_play
    
    if len(lines) <= 1:
        sys.stderr.write("File must contain at least 2 lines")
        sys.exit()
    And finally in context.
    Code:
    filename = 'playlist.txt'
    outfile = ''
    
    if len(argv) == 1:
        print "Usage: python playlister.py <input file> <output file>"
        exit()
    
    if len(argv) > 1 and argv[1]:
        filename = argv[1]
    if len(argv) > 2 and argv[2]:
        outfilename = argv[2]
        outfile = open(outfilename, 'w')
    else:
        outfile = stdout
    
    
    file = open(filename, 'r')
    
    lines = {}
    required_plays = {}
    
    time_to_play_all_required = 0
    
    playlist = []
    
    for line in file.readlines():
        name, seconds_long, min_playtime_minutes = map(str.strip, line.split(','))
        seconds_long = int(seconds_long)
        min_playtime_minutes = int(min_playtime_minutes)
        lines[name] = (seconds_long, min_playtime_minutes)
        time_to_play_all_required += min_playtime_minutes
        times_to_play = (min_playtime_minutes * 60) / seconds_long
        required_plays[name] = times_to_play
    
    if len(lines) <= 1:
        sys.stderr.write("File must contain at least 2 lines")
        sys.exit()
    
    #print required_plays
    print "Required playtime in minutes: " + str(time_to_play_all_required)
    
    keys = required_plays.keys()
    all_keys = keys[:]
    actual_required_playtime_secs = 0
    
    required_playlist = []
    for key in all_keys:
        required_playlist.extend([key] * required_plays[key])
    
    actual_plays = {}
    
    while len(required_playlist) > 0:
        required_playlist_temp = required_playlist[:]
        last_item = None
        next_item = None
        if len(playlist) >= 1:
            last_item = playlist[-1]
            required_playlist_temp = [x for x in required_playlist_temp if x != last_item]
        if len(playlist) >= 3:
            last_items = playlist[-3:]
            required_playlist_temp = [x for x in required_playlist_temp if x not in last_items]
        if len(required_playlist_temp) == 0:
            all_keys_except_last = [x for x in all_keys if x != last_item]
            next_item = all_keys_except_last[random.randint(0, len(all_keys_except_last) - 1)]
        else:
            next_item = required_playlist_temp[random.randint(0, len(required_playlist_temp) - 1)]
            required_playlist.remove(next_item)
        playlist.append(next_item)
        actual_required_playtime_secs += lines[next_item][0]
        if next_item not in actual_plays:
            actual_plays[next_item] = 0
        actual_plays[next_item] += 1
    
    print "Actual time in minutes to play all required ads: " + str(actual_required_playtime_secs / 60)
    
    total_playtime_secs = actual_required_playtime_secs
    max_time_secs = 60 * 60
    while total_playtime_secs < max_time_secs:
        all_keys_except_last_played = all_keys[:]
        all_keys_except_last_played.remove(playlist[len(playlist) - 1])
        all_keys_copy = all_keys_except_last_played[:]
        for key in all_keys_copy:
            if lines[key][0] + total_playtime_secs > max_time_secs and key in all_keys_except_last_played:
                #print "removing key: " + key
                all_keys_except_last_played.remove(key)
        if len(all_keys_except_last_played) == 0:
            break
        idx = random.randint(0, len(all_keys_except_last_played) - 1)
        newkey = all_keys_except_last_played[idx]
        if total_playtime_secs + lines[newkey][0] > max_time_secs:
                           break
        playlist.append(newkey)
        total_playtime_secs += lines[newkey][0]
        if newkey not in actual_plays:
            actual_plays[newkey] = 0
        actual_plays[newkey] += 1
    
    print "Total playtime in minutes: " + str(total_playtime_secs / 60.0)
    for key in actual_plays:
        print key + ": " + str(required_plays[key]) + " required / " + str(actual_plays[key]) + " actual"
    for ad in playlist:
        outfile.write(ad)
        outfile.write("\n" * (lines[ad][0] / 15))
    Now have I done something massively wrong? As I can't see it.
  • bvdet
    Recognized Expert Specialist
    • Oct 2006
    • 2851

    #2
    Function map() returns a list which is one object. This should work:
    Code:
    tuple(map(str.strip, line.split(',')))
    The tuple will expand to make the three assignments.

    BTW, great job with the code tags!

    BV

    Comment

    • f0rd
      New Member
      • Mar 2010
      • 4

      #3
      Sadly still no luck, same error.

      Comment

      • bvdet
        Recognized Expert Specialist
        • Oct 2006
        • 2851

        #4
        Well, I was wrong. The list expands also.

        Is it possible you have a blank line in the file? Add a print statement before the offending statement to see what the contents of line is.

        Code:
        for line in file.readlines():
            if line.strip():
                name, seconds_long, min_playtime_minutes = map(str.strip, line.split(','))

        Comment

        • Glenton
          Recognized Expert Contributor
          • Nov 2008
          • 391

          #5
          Hi. This is an interesting one to debug. How many lines is the file? Because putting in a print line command would probably give you a clue. The line where you get the error *should* work. So perhaps there's another line in which an extra comma appears or something like that?

          Here's some interactive playing around I did, which shows that the map function you used is not at fault:
          Code:
          In [2]: s="Sound004,30,3"
          
          In [3]: map(str.strip,s.split(','))
          Out[3]: ['Sound004', '30', '3']
          
          In [4]: n,l,m = map(str.strip,s.split(','))
          
          In [5]: n,l,m
          Out[5]: ('Sound004', '30', '3')
          So that seems to be working fine. Let us know what happens with the print statement I mentioned earlier.

          Comment

          Working...