Error splitting string python, has length 1, 2 is required

TheEditor :

I can't figure out what I'm doing wrong here.

Here is my data:

clientSelect : Long Company Name Inc.
server1Info : Server1
server1Pic : 200330135637030000.jpg
server2Info : Server2
server2Pic : 200330140821800000.jpg
modemInfo : Aries
modemPic : 200330140830497000.jpg
routerInfo : Router
routerPic : 200330140842144000.jpg
switchInfo : Switch1
switchGallery_media : 200330140859161000.jpg
buttonSubmit : Submit

::end::

This is currently in a string. It's pulled from sharepoint via

lines = folder.get_file('main_equipment_list.txt')
lines =  lines.replace(",", "")

for row in lines.split(","):

SOMETHING HERE TO SPLIT.

Thereplace line is to deal with some commas in some of the info that shouldn't be there before splitting.

Everything is fine up until its split then I can't get it into a dict from there.

I've tried

d = dict(s.split(':') for s in lines)
print d

That gets me

  File "testShare.py", line 24, in <module>
    d = dict(s.split(':') for s in row)
ValueError: dictionary update sequence element #0 has length 1; 2 is required

So what want is to get that into a dict.

If I do this:

for row in lines.split(","):
    print(row)

I get:

clientSelect : Long Company Name Inc.
server1Info : Server1
server1Pic : 200330135637030000.jpg
server2Info : Server2
server2Pic : 200330140821800000.jpg
modemInfo : Aries
modemPic : 200330140830497000.jpg
routerInfo : Router
routerPic : 200330140842144000.jpg
switchInfo : Switch1
switchGallery_media : 200330140859161000.jpg
buttonSubmit : Submit

::end::

But if I do this:

for row in lines.split(","):
#    print(row)
    for s in row:
        print(s[0])

I get a single character on each line. And if I do:

for row in lines.split(","):
#    print(row)
    for s in row:
        print(s[1])

I get an out of range error.

Edit:

I went back and started over. Everything was fine until I tried splitting up the rows. Here is what works.

lines = folder.get_file('main_equipment_list.txt')
lines = lines.rsplit("\n",2)[0]
d = {}
for line in lines.split("\n"):
    if line.strip():
        try:
            k, v = map(str.strip, line.split(":"))
            d[k] = v
        except ValueError as ex:
            print("on line" % (ex, line))
            pass

print(d)

What I think was going wrong was multiple things. Mostly my unfamiliarity with python, and whitespace/extra characters messing me up

I was doing some testing. If I use this:

lines = lines.rsplit("\n",2)[0]

for line in lines.split("\n"):
    if line.strip():
        try:
            x = line.split(":", 1)                                                                                                                                  
            print(x)

        except ValueError as ex:
            print("on line" % (ex, line))
            pass

I get:

['switchGallery_media ', ' 200330140859161000.jpg\r']

Either way it works and I understand a few things better. Thank you @RoadRunner for the help and tips on showing errors.

RoadRunner :

You are getting this error because you are splitting the empty newline and the ::end:: at the end of the file. Splitting those lines will both give ['\n'] and ['', '', 'end', '', '']. Dictionaries are key: value based, and will raise a ValueError exception if you give it more or less items to process.

You can reproduce this exception easily in the shell:

>>> x = ["1:2", "3:4"]
>>> dict(y.split(":") for y in x)
{'1': '2', '3': '4'}
>>> x = ["1:2", "3"]
>>> dict(y.split(":") for y in x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: dictionary update sequence element #1 has length 1; 2 is required
>>> x = ["1:2:3", "4:5:6"]
>>> dict(y.split(":") for y in x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: dictionary update sequence element #0 has length 3; 2 is required

You can avoid this by stripping empty whitespace or newlines with strip() and unpacking the split items into a tuple, which is guarded by a try..catch block. This exception handler will trigger when we run into an invalid line.

with open("data.txt") as f:
    d = {}

    for line in f:

        # avoid empty lines
        if line.strip():
            try:

                # unpack key and value into tuple and strip whitespace
                k, v = map(str.strip, line.split(":"))

                # strip whitespace after splitting
                d[k] = v

            # catch error and print it out
            # use pass to just ignore the error
            except ValueError as ex:
                print("%s occured on line: %s" % (ex, line))
                pass

    print(d)

Output:

too many values to unpack (expected 2) occured on line: ::end::
{'clientSelect': 'Long Company Name Inc.', 'server1Info': 'Server1', 'server1Pic': '200330135637030000.jpg', 'server2Info': 'Server2', 'server2Pic': '200330140821800000.jpg', 'modemInfo': 'Aries', 'modemPic': '200330140830497000.jpg', 'routerInfo': 'Router', 'routerPic': '200330140842144000.jpg', 'switchInfo': 'Switch1', 'switchGallery_media': '200330140859161000.jpg', 'buttonSubmit': 'Submit'}

Notice how I printed the exception to see what happened. The code wasn't able to unpack the key and value pairs, because it had more than 2 items to unpack from line.split(":"). The code still created the dictionary, but I logged the exceptions to see what was really happening. This is handy to see where your code is going wrong.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=376425&siteId=1