problems when unpacking tuple ...

Discussion in 'Python' started by harold, Apr 22, 2006.

  1. harold

    harold Guest

    Dear all,

    Maybe I stared on the monitor for too long, because I cannot find the
    bug ...
    My script "transition_filter.py" starts with the following lines:

    import sys

    for line in sys.stdin :
    try :
    for a,b,c,d in line.split() :
    pass

    except ValueError , err :
    print line.split()
    raise err

    The output (when given the data I want to parse) is:
    ['0.0','1','0.04','0']
    Traceback (most recent call last):
    File "transition_filter.py", line 10, in ?
    raise err
    ValueError: need more than 3 values to unpack

    What is going wrong here? Why does python think that
    I want to unpack the outcome of line.split() into three
    values instead of four? I must be really tired, but I just
    cannot see the problem. Any clues??

    Thanks,

    - harold -
     
    harold, Apr 22, 2006
    #1
    1. Advertising

  2. harold

    Tim Chase Guest

    > for a,b,c,d in line.split() :
    >

    [snip]
    >
    > The output (when given the data I want to parse) is:
    > ['0.0','1','0.04','0']


    You'll notice that you're not passing any parameters to
    split(). By default, it splits on whitespace, and your
    input doesn't have any whitespace in it. Thus, you're
    actually only getting *one* (not three) elements back. Try
    using split(",") instead.

    -tkc
     
    Tim Chase, Apr 22, 2006
    #2
    1. Advertising

  3. harold

    Rene Pijlman Guest

    harold:
    >The output (when given the data I want to parse) is:


    If you'd told us that data, and told us what version of Python you're
    using, we could have reproduced the problem to look into it.

    >ValueError: need more than 3 values to unpack
    >
    >Why does python think that I want to unpack the outcome of
    >line.split() into three values instead of four?


    That's not what it says. It says there are only 3 values in the outcome,
    and it needs more (4 to be precise).

    --
    René Pijlman
     
    Rene Pijlman, Apr 22, 2006
    #3
  4. harold wrote:
    > Dear all,
    >
    > Maybe I stared on the monitor for too long, because I cannot find the
    > bug ...
    > My script "transition_filter.py" starts with the following lines:
    >
    > import sys
    >
    > for line in sys.stdin :
    > try :
    > for a,b,c,d in line.split() :
    > pass
    >
    > except ValueError , err :
    > print line.split()
    > raise err
    >
    > The output (when given the data I want to parse) is:
    > ['0.0','1','0.04','0']
    > Traceback (most recent call last):
    > File "transition_filter.py", line 10, in ?
    > raise err
    > ValueError: need more than 3 values to unpack
    >
    > What is going wrong here? Why does python think that
    > I want to unpack the outcome of line.split() into three
    > values instead of four? I must be really tired, but I just
    > cannot see the problem. Any clues??
    >


    The 3 values are coming from the first element in the list '0.0' -
    change it to '0' and you should get: ValueError: need more than 1 value
    to unpack.
    See? it's trying to get a,b,c,d from each element of the list not the
    whole list.

    Gerard
     
    Gerard Flanagan, Apr 22, 2006
    #4
  5. harold

    harold Guest

    Rene Pijlman schrieb:

    > harold:
    > >The output (when given the data I want to parse) is:

    >
    > If you'd told us that data, and told us what version of Python you're
    > using, we could have reproduced the problem to look into it.
    >


    Thank you for the answers and sorry that I did not provide more
    information in the first place.
    My data file is white space seperated data (space seperated data to be
    precise) and I am
    using python 2.4.2


    As can be seen, the output of the print statement in the lines

    except ValueError , err:
    print line.split()
    raise err

    has exactly four values...


    > >ValueError: need more than 3 values to unpack
    > >
    > >Why does python think that I want to unpack the outcome of
    > >line.split() into three values instead of four?

    >
    > That's not what it says. It says there are only 3 values in the outcome,
    > and it needs more (4 to be precise).



    A similar error happens in an interpreter session, when typing
    >>> for line in ["1 2 3 4"] :

    .... for a,b,c,d in line.split() :
    .... pass
    ....
    Traceback (most recent call last):
    File "<stdin>", line 2, in ?
    ValueError: need more than 1 value tyo unpack

    maybe this might help to track down the error.
    Thanks!

    - harold -
     
    harold, Apr 22, 2006
    #5
  6. harold

    harold Guest

    Thank you Gerard.
    This must be the problem. Now I can get it working.
     
    harold, Apr 22, 2006
    #6
  7. harold

    Rene Pijlman Guest

    harold:
    >A similar error happens in an interpreter session, when typing
    >>>> for line in ["1 2 3 4"] :

    >... for a,b,c,d in line.split() :
    >... pass
    >...
    >Traceback (most recent call last):
    > File "<stdin>", line 2, in ?
    >ValueError: need more than 1 value tyo unpack
    >
    >maybe this might help to track down the error.


    Suppose the code was:

    for x in line.split():

    line.split() yields one list with 4 items. The loop will be performed 4
    times, assigning one value of the list to x with every iteration. In your
    code, x is a tuple with 4 elements: a,b,c,d. So with every iteration one
    value is assigned to that tuple. Since the value is not a sequence of 4
    items, this fails.

    There's two sensible things you can do:

    for line in ["1 2 3 4"]:
    a,b,c,d = line.split()

    for line in ["1 2 3 4"]:
    for a in line.split():

    --
    René Pijlman
     
    Rene Pijlman, Apr 22, 2006
    #7
  8. Em Sáb, 2006-04-22 às 09:21 -0700, harold escreveu:
    > for line in sys.stdin :
    > try :
    > for a,b,c,d in line.split() :
    > pass
    >
    > except ValueError , err :
    > print line.split()
    > raise err


    Try this:

    for a, b, c, d in sys.stdin:
    print a, b, c, d

    --
    Felipe.
     
    Felipe Almeida Lessa, Apr 22, 2006
    #8
  9. harold wrote:
    > Thank you Gerard.
    > This must be the problem. Now I can get it working.


    Good! I got confused thinking about it too, but I think you just had
    one loop too many.

    for line in sys.stdin :
    try :
    a,b,c,d = line.split()

    not:

    for line in sys.stdin :
    try :
    for a,b,c,d in line.split() :
    pass

    Gerard
     
    Gerard Flanagan, Apr 22, 2006
    #9
  10. Em Sáb, 2006-04-22 às 14:25 -0300, Felipe Almeida Lessa escreveu:
    > Em Sáb, 2006-04-22 às 09:21 -0700, harold escreveu:
    > > for line in sys.stdin :
    > > try :
    > > for a,b,c,d in line.split() :
    > > pass
    > >
    > > except ValueError , err :
    > > print line.split()
    > > raise err

    >
    > Try this:
    >
    > for a, b, c, d in sys.stdin:
    > print a, b, c, d
    >


    Forget that. It was stupid. You should try this instead:

    for line in sys.stdin:
    a, b, c, d = line.split()

    --
    Felipe.
     
    Felipe Almeida Lessa, Apr 22, 2006
    #10
  11. harold

    harold Guest

    Thanks for all your answer!
    Of course, I wanted to assign the outcome of the split(), not to
    iterate
    over them. Thinks are done so easy in python that, sometimes, one
    does not even notice that one actually does them ;-)
    Cheers,

    - harold -
     
    harold, Apr 22, 2006
    #11
  12. harold

    John Machin Guest

    On 23/04/2006 2:21 AM, harold wrote:
    > Dear all,
    >
    > Maybe I stared on the monitor for too long, because I cannot find the
    > bug ...


    You already have your answer, but below are clues on how to solve such
    problems much faster by yourself.

    > My script "transition_filter.py" starts with the following lines:
    >
    > import sys
    >
    > for line in sys.stdin :
    > try :
    > for a,b,c,d in line.split() :
    > pass
    >
    > except ValueError , err :
    > print line.split()
    > raise err
    >
    > The output (when given the data I want to parse) is:
    > ['0.0','1','0.04','0']


    I doubt it. Much more likely is
    ['0.0', '1', '0.04', '0']
    It doesn't matter in this case, but you should really get into the
    habit of copy/pasting *EXACTLY* what is there, not re-typing what you
    think is there.

    > Traceback (most recent call last):
    > File "transition_filter.py", line 10, in ?
    > raise err
    > ValueError: need more than 3 values to unpack
    >
    > What is going wrong here? Why does python think that
    > I want to unpack the outcome of line.split() into three
    > values instead of four? I must be really tired, but I just
    > cannot see the problem. Any clues??
    >


    Clues:
    1. Use the print statement to show what you have.
    2. Use the built-in repr() function to show *unambiguously* what you
    have -- very important when you get into Unicode and encoding/decoding
    problems; what you see after "print foo" is not necessarily what
    somebody using a different locale/codepage will see.
    3. In some cases (not this one), it is also helpful to print the type()
    of the data item.

    Example:

    C:\junk>type harold.py
    import sys

    def harold1():
    for line in sys.stdin :
    try :
    for a,b,c,d in line.split() :
    pass

    except ValueError , err :
    print line.split()
    raise err

    def harold2():
    for line in sys.stdin:
    print "line =", repr(line)
    split_result = line.split()
    print "split result =", repr(split_result)
    for x in split_result:
    print "about to try to unpack the sequence", repr(x), "into
    4 items"

    a, b, c, d = x

    harold2()

    C:\junk>harold.py
    0.0 1 0.04 0
    a b c d e f
    ^Z
    line = '0.0 1 0.04 0\n'
    split result = ['0.0', '1', '0.04', '0']
    about to try to unpack the sequence '0.0' into 4 items
    Traceback (most recent call last):
    File "C:\junk\harold.py", line 22, in ?
    harold2()
    File "C:\junk\harold.py", line 20, in harold2
    a, b, c, d = x
    ValueError: need more than 3 values to unpack

    =====

    Coding style: Not inventing and using your own dialect makes two-way
    communication much easier in any language (computer or human). Consider
    reading and following http://www.python.org/dev/peps/pep-0008/

    Hope this helps,
    John
     
    John Machin, Apr 23, 2006
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Paul McGuire
    Replies:
    8
    Views:
    1,263
    Mark Wooding
    Nov 24, 2004
  2. James Stroud

    Tuple Unpacking in raise

    James Stroud, Jun 21, 2005, in forum: Python
    Replies:
    3
    Views:
    423
    James Stroud
    Jun 21, 2005
  3. Patrick Toomey

    Can my own objects support tuple unpacking?

    Patrick Toomey, Mar 27, 2008, in forum: Python
    Replies:
    2
    Views:
    329
  4. Martin Geisler

    Tuple parameter unpacking in 3.x

    Martin Geisler, Oct 2, 2008, in forum: Python
    Replies:
    20
    Views:
    796
    Aaron \Castironpi\ Brady
    Oct 11, 2008
  5. imageguy
    Replies:
    7
    Views:
    307
    John Machin
    Jan 13, 2009
Loading...

Share This Page