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.
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.