Iterating thru list for lxml form submission - python-3.x

I'm pretty new to Python and even more new to lxml, but what I'm trying to do seems really simple but I can't figure out what I'm doing wrong.
I have this code with the goal of feeding a list of values (list object ISBN) to lxml to submit to a search field:
for i in ISBN:
page.forms[0].fields['_nkw'] = ISBN[i]
blah blah blah
I get this error after running:
Traceback (most recent call last):
page.forms[0].fields['_nkw'] = ISBN[i]
TypeError: list indices must be integers, not str
Obviously there has to be a way to iterate through a list of values to feed to a form, but clearly I don't know it :)
EDIT: FYI the code works fine when replacing ISBN[i] with hard input.
EDIT 2: contents of ISBN list object as requested:
['9781608319053', '9780321558237', '9781932735413', '9781416059516', '9781437708257', '9780781780582', '9781437701517', '9780323065801', '9780890420256', '9780323079334', '9781599417042', '9780781771535', '9781416031215', '9780312601430', '9780781775250', '9781591263333', '9780071748896', '9780133669510', '9781416045748', '9780781771566', '9781437728019', '9780323065849', '9781416066675', '9780735579965', '9780323078917', '9781437735826', '9781603595681', '9780321696724', '9780321558145', '9781933107981', '9780138024611']

The trouble is with your loop over and use of the ISBN variable. You don't need to be indexing it during your assignment, since i already holds an element of the list, extracted as part of the loop. You're getting an exception because you can't index a list with a string, even if that string came out of the list itself.
Instead, use page.forms[0].fields['_nkw'] = i.
Or if you need the index into the ISBN list for later code that you haven't shown, keep the assignment as it is, and change the loop declaration to:
for i in range(len(ISBN)):

Related

Stringify list back to list in Python 3

I have a list like string which I want to convert to a list, but so far I'm unlucky. The string is like follows:
my_string="[749385,435,'20/07/11 05:32','34035',1298,tmp_host_name,'312642',6577,tmp_guest_name,'-0.5,-1.0','2.5,3.0','9.5 ',tmp_league_name,'2' ,'0','0','0','4',' 2','0','1','0.0,-0.5','4.5','1.0',1]"
My problems are:
I can't use eval because some of the items in the list to be are not strings, so it gives me
eval(my_string)
>NameError: name 'tmp_host_name' is not defined
I can't use ast.literal_eval because again, it gives an error
ast.literal_eval(my_string)
>ValueError: malformed node or string: <_ast.Name object at 0x0000017E7DA9E488>
and I can't do it with strip and split because some of the items are like '2.5,3.0' and this is splitted as well, something I don't want
my_string.strip('][').split(',')
['749385','435',"'20/07/11 05:32'", "'34035'",'1298','tmp_host_name',"'312642'",'6577','tmp_guest_name',"'-0.5","-1.0'","'2.5","3.0'","'9.5','tmp_league_name', "'2' ","'0'","'0'","'0'","'4'","' 2'","'0'","'1'","'0.0","-0.5'","'4.5'","'1.0'",'1']
One possible route is to use my last approach and verify that every element has 2 ' characters, and if not, merge it with the following element, but I'm looking for something a little more pythonic.
newlist=list()
for el in k:
if el.startswith("'") and el.endswith("'"):newlist.append(el)
elif el.startswith("'"):
compound=el
elif el.endswith("'"):
compound+=el
newlist.append(compound)
else:newlist.append(el)
Problem is, if I do this, the resulting list loses its order and becomes useless
Thanks!

Defining labels in Tkinter using values from another list

Well, I was trying to define Labels from another list that contain hours but no sucess.
def loop_label():
for item in Acd_horario:
Acd_horario[item] = Label(framerajada, text=[Acd_horario[item]],
font=font_acd, bg=bg_acd, fg=fg_acd, bd=bd_acd,
relief=relief_acd)
loop_label()
I tried like above, but no sucess. The other list I`m using is from another class, with gets the hour of another list of objects from the class itself:
Acd_lista = [Acd_0715, Acd_0745, Acd_0815, Acd_0845, Acd_0915, Acd_0945,
Acd_1015, Acd_1045, Acd_1115, Acd_1145,
Acd_1215, Acd_1245, Acd_1315, Acd_1345, Acd_1415, Acd_1445,
Acd_1515, Acd_1545, Acd_1615, Acd_1645,
Acd_1715, Acd_1745, Acd_1815, Acd_1845, Acd_1915, Acd_1945,
Acd_2015]
Acd_horario = [i.horario for i in Acd_lista]
Maybe is my logic that isn't right. Anyone has any idea on this?
The error I receive is: TypeError list indices must be integers or slices, not str

Saving ord(characters) from different lines(one string) in different lists

i just can't figure it out.
I got a string with some lines.
qual=[abcdefg\nabcedfg\nabcdefg]
I want to convert my characters to the ascii value and saves those values in an other list for each line.
value=[[1,2,3,4,5,6],[1,2,3,4,5,6],[1,2,3,4,5,6]
But my codes saves them all in one list.
values=[1,2,3,4,5,6,1,2,3,4,5,6,1,2,3,4,5,6]
First of all my code:
for element in qual:
qs = ord(element)
quality_code.append(qs)
I also tried to split() the string but the result is still the same
qual=line#[:-100]
qually=qual.split()
for list in qually:
for element in list:
qs = ord(element)
quality.append(qs)
My next attempt was:
for element in qual:
qs = ord(element)
quality_code.append(qs)
for position in range(0, len(quality_code)):
qual_liste[position].append(quality_code[position])
With this code an IndexError(list index out of range) occurs.
There is probably a way with try and except but i dont get it.
for element in qual:
qs = ord(element)
quality_code.append(qs)
for position in range(0, len(quality_code)):
try:
qual_liste[position].append(quality_code[position])
except IndexError:
pass
With this code the qual_lists stays empty, probably because of the pass
but i dont know what to insert instead of pass.
Thanks a lot for help. I hope my bad english is excusable .D
Here you go, this should do the trick:
qual="abcdefg\nabcedfg\nabcdefg"
print([[ord(ii) for ii in i] for i in qual.split('\n')])
List comprehension is always the answer.

Python3 - Advice on a while loop with range?

Good afternoon! I am relatively new to Python - and am working on an assignment for a class.
The goal of this code is to download a file, add a line of data to the file, then create a while loop that iterates through each line of data, and prints out the city name and the highest average temp from the data for that city.
My code is below - I have the output working, no problem. The only issue I am running into is an IndexError: list index out of range - at the end.
I have searched on StackOverflow - as well as digging into the range() function documentation online with Python. I think I just need to figure to the range() properly, and I'd be done with it.
If I take out the range, I get the same error - so I tried to change the for/in to - for city in mean_temps:
The result of that was that the output only showed 4 of the 7 cities - skipping every other city.
Any advice would be greatly appreciated!
here is my code - the screenshot link below shows output and the error as well:
!curl https://raw.githubusercontent.com/MicrosoftLearning/intropython/master/world_temp_mean.csv -o mean_temp.txt
mean_temps = open('mean_temp.txt', 'a+')
mean_temps.write("Rio de Janeiro,Brazil,30.0,18.0")
mean_temps.seek(0)
headings = mean_temps.readline().split(',')
print(headings)
while mean_temps:
range(len(city_temp))
for city in mean_temps:
city_temp = mean_temps.readline().split(',')
print(headings[0].capitalize(),"of", city_temp[0],headings[2], "is", city_temp[2], "Celsius")
mean_temps.close()
You have used a while loop, when you actually want to use a for loop. You have no condition on your while loop, therefore, it will evaluate to True, and run forever. You should use a for loop in the pattern
for x in x:
do stuff
In your case, you will want to use
for x in range(len(city_temp)):
for city in means_temp:
EDIT:
If you have to use a while loop, you could have variable, x, that is incremented by the while loop. The while loop could run while x is less than range(len(city_temp)).
A basic example is
text = "hi"
counter = 0
while counter < 10:
print(text)
counter += 1
EDIT 2:
You also said that they expected you to get out of a while loop. If you want a while loop to run forever unless a condition is met later, you can use the break command to stop a while or for loop.
I've been stuck with this as well with the index error. My original code was:
city_temp = mean_temp.readline().strip(" \n").split(",")
while city_temp:
print("City of",city_temp[0],headings[2],city_temp[2],"Celcius")
city_temp = mean_temp.readline().split(",")
So I read the line then, in the loop, print the line, create the list from reading the line and if the list is empty, or false, break. Problem is I was getting the same error as yourself and this is because city_temp is still true after reading the last line. If you add..
print(city_temp)
to your code you will see that city_temp returns as "" and even though it's an empty string the list has content so will return true. My best guess (and it is a guess) it looks for the split condition and returns back nothing which then populates the list as an empty string.
The solution I found was to readline into a string first (or at the end of the whole loop) before creating the list:
city_temp = mean_temp.readline()
while city_temp:
city_temp = city_temp.split(',')
print(headings[0].capitalize(),"of",city_temp[0],headings[2],"is",city_temp[2],"Celcius")
city_temp = mean_temp.readline()
This time city_temp is checked by the while loop as a string and now returns false. Hope this helps from someone else who struggled with this

Proper Syntax for List Comprehension Involving an Integer and a Float?

I have a List of Lists that looks like this (Python3):
myLOL = ["['1466279297', '703.0']", "['1466279287', '702.0']", "['1466279278', '702.0']", "['1466279268', '706.0']", "['1466279258', '713.0']"]
I'm trying to use a list comprehension to convert the first item of each inner list to an int and the second item to a float so that I end up with this:
newLOL = [[1466279297, 703.0], [1466279287, 702.0], [1466279278, 702.0], [1466279268, 706.0], [1466279258, 713.0]]
I'm learning list comprehensions, can somebody please help me with this syntax?
Thank you!
[edit - to explain why I asked this question]
This question is a means to an end - the syntax requested is needed for testing. I'm collecting sensor data on a ZigBee network, and I'm using an Arduino to format the sensor messages in JSON. These messages are published to an MQTT broker (Mosquitto) running on a Raspberry Pi. A Redis server (also running on the Pi) serves as an in-memory message store. I'm writing a service (python-MQTT client) to parse the JSON and send a LoL (a sample of the data you see in my question) to Redis. Finally, I have a dashboard running on Apache on the Pi. The dashboard utilizes Highcharts to plot the sensor data dynamically (via a web socket connection between the MQTT broker and the browser). Upon loading the page, I pull historical chart data from my Redis LoL to "very quickly" populate the charts on my dashboard (before any realtime data is added dynamically). I realize I can probably format the sensor data the way I want in the Redis store, but that is a problem I haven't worked out yet. Right now, I'm trying to get my historical data to plot correctly in Highcharts. With the data properly formatted, I can get this piece working.
Well, you could use ast.literal_eval:
from ast import literal_eval
myLOL = ["['1466279297', '703.0']", "['1466279287', '702.0']", "['1466279278', '702.0']", "['1466279268', '706.0']", "['1466279258', '713.0']"]
items = [[int(literal_eval(i)[0]), float(literal_eval(i)[1])] for i in myLOL]
Try:
import json
newLOL = [[int(a[0]), float(a[1])] for a in (json.loads(s.replace("'", '"')) for s in myLOL)]
Here I'm considering each element of the list as a JSON, but since it's using ' instead of " for the strings, I have to replace it first (it only works because you said there will be only numbers).
This may work? I wish I was more clever.
newLOL = []
for listObj in myLOL:
listObj = listObj.replace('[', '').replace(']', '').replace("'", '').split(',')
newListObj = [int(listObj[0]), float(listObj[1])]
newLOL.append(newListObj)
Iterates through your current list, peels the string apart into a list by replace un-wanted string chracters and utilizing a split on the comma. Then we take the modified list object and create another new list object with the values being the respective ints and floats. We then append the prepared newListObj to the newLOL list. Considering you want an actual set of lists within your list. Your previously documented input list actually contains strings, which look like lists.
This is a very strange format and the best solution is likely to change the code which generates that.
That being said, you can use ast.literal_eval to safely evaluate the elements of the list as Python tokens:
>>> lit = ast.literal_eval
>>> [[lit(str_val) for str_val in lit(str_list)] for str_list in myLOL]
[[1466279297, 703.0], [1466279287, 702.0], [1466279278, 702.0], [1466279268, 706.0], [1466279258, 713.0]]
We need to do it twice - once to turn the string into a list containing two strings, and then once per resulting string to convert it into a number.
Note that this will succeed even if the strings contain other valid tokens. If you want to validate the format too, you'd want to do something like:
>>> def process_str_list(str_list):
... l = ast.literal_eval(str_list)
... if not isinstance(l, list):
... raise TypeError("Expected list")
... str_int, str_float = l
... return [int(str_int), float(str_float)]
...
>>> [process_str_list(str_list) for str_list in myLOL]
[[1466279297, 703.0], [1466279287, 702.0], [1466279278, 702.0], [1466279268, 706.0], [1466279258, 713.0]]
Your input consists of a list of strings, where each string is the string representation of a list. The first task is to convert the strings back into lists:
import ast
lol2 = map(ast.literal_eval, mylol) # [['1466279297', '703.0'], ...]
Now, you can simply get int and float values from lol2:
newlol = [[int(a[0]), float(a[1])] for a in lol2]

Resources