why python if while ends in a dead loop - python

order = 2
selected = 0
while selected < 21: # because I can only select 20 rows the most once.
current_tr = driver.find_element_by_xpath('/ html / body / table / tbody / tr / td / div / div[3] / table / tbody / tr[%d]' % order) # form line 1. below the table's header
if current_tr.get_attribute("bgcolor") is None: # no bgcolor means not yet reviewed
driver.find_element_by_xpath("//td[2]/div/a").click() # check the onclick content
div_content = driver.find_element_by_xpath("//td[2]/div/div").text # fetch onclick content
driver.find_element_by_xpath("//td[2]/div/div/a").click() # close the onclick content
print(div_content)
if "car" in div_content: #judge if certain string exists in onclick content
list_content = div_content.split("【car】")
car_close = list_content[1].strip() # fetch the content
list_car = car_close.split(" ")
car = list_doi[0]
print(car)
orderminus = order - 1
driver.find_element_by_xpath('// *[ # id = "%d"] / td[6] / a' % orderminus).click() # pick this row,
time.sleep(1)
selected = selected + 1
order = order + 0 #if this row is picked, the row will disappear, so the order won't change
else: ###problem is here, the else branch seems like never been executed ? otherwise the if always stands? no, not possible. there are ones exclude "car", the problem occurs at the first instance of div_content without "car"
order = order + 1 # if "car" is not in
time.sleep(1)
else: # if already reviewed, order + 1
order = order + 1
above is my code using selenium to navigate the webpage with a table.
First judgement: if the current row is reviewed,
not yet reviewed? ok, print the info;
already reviewed?skip it.
then plus judgement: if there certain string "car" in the info:
no? skip;
yes, click it, the row disappear;
But currently when I am running this, the actual status is :
when doing the plus judement, if the string "car" is not in the info,
it keeps printing the info, it seems it not doing the else branch, is doing the line 6_9 in this snippet, always, dead end loop.
Why? anybody give me a clue?
to make things clear, i have simplified my code as below:
list = []
list.append("ff122")
list.append("carff")
list.append("ff3232")
list.append("ffcar")
list.append("3232")
order = 0
selected = 0
while selected < 6:
current_tr = list[order]
print("round %d %s" % (order, current_tr))
if "ff" in current_tr:
print("ff is in current_tr")
if "car" in current_tr:
print("car")
selected = selected + 1
order = order + 0
else:
order = order + 1
print("order is %d" % order)
else: # if already reviewed, order + 1
order = order + 1
print("order is %d" % order)
everybody can run this, what I need to do is firstly filter the "ff", if "ff" exists, then filter "car". both two conditions TRUE, selected +1, until selected reach certain number. in real instance, don't doubt that the list is long enough.

Related

PYTHON SQLITE selecting multiple where conditions that may or may not exist

Working on some code that uses pysimplegui as the UI and SQlite for the data sorting. I'm using SQLite's execute function to select data based on input from the user in the UI through variables. For example user wants to search for part name they input all or part of the name into the box, hit the search button which then runs my "parts_search" method, which will then only filter the result based on part name. OR the user enters information in multiple boxes which then filters based on the boxes that have information.
This here is runnable code provided you add a file base1.db in the same folder location as the script itself
import PySimpleGUI as sg
import os.path
import sqlite3
# sql var
c = None
conn = None
setup = None
# list var
parts = []
def sql():
global setup
conn_sql()
c.execute("""CREATE TABLE IF NOT EXISTS parts (part_name TEXT, part_number TEXT, part_series TEXT,
part_size INTEGER, job_type TEXT)""")
conn.commit()
if conn:
conn.close()
def conn_sql():
global c
global conn
# SQL connection var
if os.path.isfile('./base1.db'):
conn = sqlite3.connect('base1.db')
c = conn.cursor()
def main_gui_parts():
global parts
layout = [[sg.Text('Part Name: '), sg.Input(size=(20, 1), key='-PName-'), sg.Text('Part Series:'),
sg.Input(size=(10, 1), key='-PSeries-')],
[sg.Text('Part Number:'), sg.Input(size=(20, 1), key='-PNumber-'), sg.Text('Part Size:'),
sg.Input(size=(10, 1), key='-PSize-')],
[sg.Checkbox('Fit', key='-PFit-'), sg.Checkbox('Weld', key='-PWeld-'),
sg.Checkbox('Assemble', key='-PAssemble-'),
sg.Button('Search', key='-PSearch-')],
[sg.Listbox(parts, size=(58, 10), key='-PParts-')], [sg.Button('Back', key='-PBack-')]]
window = sg.Window('parts list', layout, grab_anywhere=True)
sql()
while True:
event, values = window.read()
if event == 'Close' or event == sg.WIN_CLOSED:
break
# PART WINDOW
part_name = values['-PName-']
part_series = values['-PSeries-']
part_number = values['-PNumber-']
part_size = values['-PSize-']
fit = values['-PFit-']
weld = values['-PWeld-']
assemble = values['-PAssemble-']
if event == '-PSearch-':
print('search parts')
part_search(part_name, part_series, part_number, part_size, fit, weld, assemble)
if event == '-PBack-':
break
window.close()
def part_search(part_name, part_series, part_number, part_size, fit, weld, assemble):
global parts
conn_sql()
filter_original = """SELECT * FROM parts WHERE """
filter = filter_original
if part_name:
print('part name: ' + part_name)
if filter == filter_original:
filter += """part_name LIKE ? """
else:
filter += """AND part_name LIKE ? """
if part_series:
print('part series: ' + part_series)
if filter == filter_original:
filter += """part_series=(?) """
else:
filter += """AND part_series=(?) """
if part_number:
print('part number: ' + part_number)
if filter == filter_original:
filter += """part_number LIKE ? """ ### DONT USE LIKE???
else:
filter += """AND part_number LIKE ? """ ### DONT USE LIKE???
if part_size:
print('part size: ' + part_size)
if filter == filter_original:
filter += """part_size=(?) """
else:
filter += """AND part_size=(?) """
if fit:
print('job type: ' + str(fit))
if filter == filter_original:
filter += """job_type = fit """
else:
filter += """AND job_type = fit """
if weld:
print('job type: ' + str(weld))
if filter == filter_original:
filter += """job_type = weld """
else:
filter += """AND job_type = weld """
if assemble:
print('job type: ' + str(assemble))
if filter == filter_original:
filter += """job_type = assemble"""
else:
filter += """AND job_type = assemble"""
print(filter)
#if filter != filter_original:
#c.execute(filter, ())
#else:
#c.execute("""SELECT * FROM parts""")
main_gui_parts()
THE PROBLEM: The commented code at the bottom is where I'm having trouble figuring out (in the "part_search" method). I don't use all of the variables all the time. Only filter with the variables provided by the user. which means the tuple should only have the variables which was input by the user.
If all the variables were used this is what it would look like. c.execute(filter, (part_name, part_series, part_number, part_size, fit, weld, assemble)) but more often than not only some of those variable will have been used and may need to look like this instead. c.execute(filter, (part_name, part_series, weld)) Somehow I need the variables here to be removeable(for lack of better word)
I've been learning a lot about SQLite but I could be seeing tunnel vision and can't think of a different way to go about this.
Probably the easiest way to deal with this is to put all the filter conditions and values into lists, and then only add a WHERE clause if the length of the filters list is non-zero. For example:
query = """SELECT * FROM parts"""
filters = []
values = []
if part_name:
filters.append("""part_name LIKE ?""")
values.append(part_name)
...
if len(filters):
query += ' WHERE ' + ' AND '.join(filters)
c.execute(query, tuple(values))
Note: should your filters ever include OR conditions, you need to parenthesise them when building the query to ensure correct operation i.e.
query += ' WHERE (' + ') AND ('.join(filters) + ')'

Django queryset .iterate(): not working. Only first item is taken into account, second is ignored

I have the following code. I know the queryset contains 2 items. However, Django only creates one entry. What am I overlooking?
I know "OrderItem.objects.filter(order=order)" returns two objects. However, in the order_lines.iterate() it only creates one entry. Do I overlook something?
order_lines = OrderItem.objects.filter(order=order)
inv_ref = (str(order.order_date.year) + "-" + str(10000+order.id))
inv = Invoice.objects.create(invoice_ref=inv_ref,date=order.order_date, order=order, ship_to=order.order_ship_to, bill_to=order.order_bill_to)
value = 0
vat = 0
total = 0
commission = 0
## Looping not working properly: fix all items to be added to invoice.
for item in order_lines.iterator():
exvat = (item.price/((100+item.vat)/100))
val = item.quantity * exvat
ttl = (item.price*item.quantity)
comm = item.commission
vat_val = ttl-val
InvoiceItems.objects.create(invoice=inv, order_item=item, quantity=item.quantity, price=exvat, value=val, vat=item.vat,vat_val=vat_val,total=ttl)
value = value + val
vat = vat + vat_val
total = total + ttl
commission = commission + comm
print(item)
Do not use .iterator() as django.models.Model.objects.filter() already returns an QuerySet which implements iterator protocol (Iterable[]).
...
for item in order_lines:
...
...
Try simplified loop:
for item in order_lines:
it should work like a charm because it's already QuerySet object.

Django: how to update multiple records?

I need to update multiple records (rows) in a table.
First, I get informations to select rows to be update:
ran_st1 = 1
ran_st2 = 1
ran_bra = 'A'
pay_ide = 'FR'
bra_lib = 'Polyvitamines et oligo-éléments'
Then, I select rows to be updated:
rows= Randomisation.objects.filter(Q(ran_st1 = ran_st1) & Q(ran_st2 = ran_st2) & Q(ran_bra = ran_bra) & Q(pay_ide = pay_ide))
And then, I though to make a loop like that, but not sure:
for row in rows:
r = get_object_or_404(Randomisation, ran_ide = row.ran_ide)
r.ran_act = 1
r.save()
You can update with .update(..) [Django-doc]:
Randomisation.objects.filter(
ran_st1=ran_st1,
ran_st2 = ran_st2,
ran_bra = ran_bra,
pay_ide = pay_ide
).update(ran_act=1)
This will work with a query that looks like:
UPDATE randomisation
SET ran_act = 1
WHERE ran_st1 = 1
AND ran_st2 = 1
AND ran_bra = 'A'
AND pay_ide = 'FR'
AND bra_lib = 'Polyvitamines et oligo-elements'
This is thus done in one query, not in several queries where you each time fetch an element, update that element, and then make an update query to the database for that specific record.

graphics in python to make a task manger

I am designing a task manager for a month using graphics in python. I have created the calendar for the month of July. I would like to display the tasks for a given date, add new tasks, remove/delete tasks and save the changes to a file.
The maximum number of to do tasks for any day is 5. Initially, the list of tasks are read from a file. Each row in the file contains the date followed by a list of semi-colon separated tasks for that date. The following shows an example file:
1; Go to class;Book Train Ticket
2; Call Home
3; Wash the Clothes
7; Submit the Assignment Online
8; Give Assignment Demo;Prepare for Major
10; Take the Exam
11; Go Home
To the right of calendar, there is a textbox to enter a new task to the list of to-do tasks for the date currently being displayed. After entering the new task in the textbox, I need to click on the ’ok’ button to add it to the list. As soon as the ’ok’ button is pressed, the list of tasks being displayed should be refreshed to reflect the addition of the new task. The textbox should be cleared after the changes have been incorporated into the task list. Here's my code:
from graphics import *
win =GraphWin("Task Manager",800,800)
head = Text(Point(130,15),"July2014")
head.setSize(16)
head.draw(win)
add = Text(Point(440,28),"Add Task :")
add.setSize(17)
add.draw(win)
adde = Entry(Point(560,28),20)
adde.draw(win)
rem = Text(Point(440,78),"Remove Task:")
rem.setSize(17)
rem.draw(win)
reme = Entry(Point(570,78),20)
reme.draw(win)
addr = Rectangle(Point(680,15),Point(640,45))
addr.setFill("yellow")
addr.draw(win)
okt = Text(Point(660,30),"ok")
okt.setSize(16)
okt.draw(win)
remr = Rectangle(Point(690,60),Point(650,90))
remr.setFill("green")
remr.draw(win)
okt = Text(Point(670,75),"ok")
okt.setSize(16)
okt.draw(win)
savr =Rectangle(Point(440,120),Point(540,150))
savr.setFill("orange")
savr.draw(win)
savt = Text(Point(490,135),"Save to file")
savt.setSize(15)
savt.draw(win)
exir = Rectangle(Point(590,120),Point(650,150))
exir.setFill("red")
exir.draw(win)
exis = Text(Point(620,135),"exit")
exis.setSize(15)
exis.draw(win)
def isInside(p,rect):
rectP1 = rect.getP1();
rectP2 = rect.getP2();
if(p.getX() >= rectP1.getX() and p.getX() <= rectP2.getX() and
p.getY() >= rectP1.getY() and p.getY() <= rectP2.getY()):
return True;
else:
return False;
dtext = Text(Point(180,350),"no date selected yet")
dtext.setSize(16)
dtext.draw(win)
def rect(a):
squ = Rectangle(Point(20+((a-1)%7)*40,70+(((a-1)//7)-1)*30),Point(20+(((a- 1)%7)+1)*40,70+((a-1)//7)*30))
return squ
for i in range(1,43):
rect(i).draw(win)
l =['sun','mon','tue','wed','thu','fri','sat']
def elem(a):
p = Point(40+((a-1)%7)*40,85+(((a-1)//7)-1)*30)
sti = Text(p,l[a-1])
sti.setSize(15)
return sti
for i in range(1,8):
elem(i).draw(win)
def num(a):
p = Point(40+((a-1)%7)*40,85+(((a-1)//7)-1)*30)
b = Text(p,a-9)
return b
for j in range(10,41):
num(j).draw(win)
id = Text(Point(50,400),"id")
id.setSize(17)
id.draw(win)
task = Text(Point(200,400),"task")
task.setSize(17)
task.draw(win)
while 9 < a< 41:
inputP = win.getMouse()
if isInside(inputP,rect(a)):
dtext.setText("tasks on July"+rect(a).getText()+"are")
else:
dtext.setText("wrong")
win.getMouse()
win.close()

for loop to insert things into a tkinter window

I have Tkinter program that has to add a significant amount of data to the window so I tried to write a for loop to take care of it but since I have to use a string variable for the name of the object that Tkinter is running .insert() on the object. I didn't explain it very well here is the method
def fillWindow(self):
global fileDirectory
location = os.path.join(fileDirectory, family + '.txt')
file = open(location, 'r')
ordersDict = {}
for line in file:
(key, value) = line.split(':', 1)
ordersDict[key] = value
for key in ordersDict:
ordersDict[key] = ordersDict[key][:-2]
for item in ordersDict:
if item[0] == '#':
if item[1] == 'o':
name = 'ordered%s' %item[2:]
right here is the problem line because I have the variable that matches the name of the entry object already created but 'name' is actually a string variable so it gives me the error "AttributeError: 'str' object has no attribute 'insert'"
name.insert(0,ordersDict[item])
here is the entire class. It makes a Tkinter window and fills it with a sort of shipping screen so all the entries are for how many orders of a certain thing are needed. I'm also very new so I know that I do things the long way a lot.
class EditShippingWindow(Tkinter.Toplevel):
def __init__(self, student):
Tkinter.Toplevel.__init__(self)
self.title('Orders')
family = student
## Window Filling
ageGroupLabel = Tkinter.Label(self,text='Age Group')
ageGroupLabel.grid(row=0,column=0)
itemColumnLabel = Tkinter.Label(self,text='Item')
itemColumnLabel.grid(row=0, column=1)
costColumnLabel = Tkinter.Label(self,text='Cost')
costColumnLabel.grid(row=0, column=2)
orderedColumnLabel = Tkinter.Label(self,text='Ordered')
orderedColumnLabel.grid(row=0, column=3)
paidColumnLabel = Tkinter.Label(self,text='Paid')
paidColumnLabel.grid(row=0, column=4)
receivedColumnLabel = Tkinter.Label(self,text='Received')
receivedColumnLabel.grid(row=0, column=5)
#Item Filling
column1list = ['T-Shirt (2T):$9.00', 'T-Shirt (3T):$9.00', 'T-Shirt (4T):$9.00',
'Praise Music CD:$10.00', ':', 'Vest L(Size 6):$10.00', 'Vest XL(Size 8):$10.00',
'Hand Book (KJ/NIV):$8.75', 'Handbook Bag:$6.00', 'Memory CD (KJ/NIV):$10.00',
':', 'Vest L(size 10):$10.00', 'Vest XL(Size 12):$10.00', 'Hand Glider (KJ/NIV/NKJ):$10.00',
'Wing Runner (KJ/NIV/NKJ):$10.00', 'Sky Stormer (KJ/NIV/NKJ):$10.00', 'Handbook Bag:$5.00',
'Memory CD (S/H/C):$10.00', 'Hand Glider Freq. Flyer:$8.00', 'Wing Runner Freq. Flyer:$8.00',
'Sky Stormer Handbook:$8.00' , ':', 'Uniform T-Shirt Size (10/12/14):$13.00',
'Uniform T-Shirt Size(10/12/14):$13.00', 'Uniform T-Shirt(Adult S / M / L / XL):$13.00',
'3rd & 4th Gr. Book 1 (KJ / NIV / NKJ):$8.75', '3rd & 4th Gr. Book 2 (KJ / NIV / NKJ):$8.75',
'4th & 5th Gr. Book 1 (KJ / NIV / NKJ):$8.75', '4th & 5th Gr. Book 2 (KJ / NIV / NKJ):$8.75',
'Memory CD 3rd & 4th Gr. Book (1/2):$10.00', 'Drawstring Backpack:$5.50']
column1num = 1
for item in column1list:
num = str(column1num)
(title, price) = item.split(':')
objectName1 = 'column1row' + num
objectName1 = Tkinter.Label(self,text=title)
objectName1.grid(row=column1num, column=1)
objectName2 = 'column1row' + num
objectName2 = Tkinter.Label(self,text=price)
objectName2.grid(row=column1num, column=2)
column1num += 1
#Ordered Paid Recieved Filler
for i in range(32):
if i == 11 or i == 22 or i == 0 or i == 5:
pass
else:
width = 10
# First Column
title1 = 'ordered' + str(i)
self.title1 = Tkinter.Entry(self,width=width)
self.title1.grid(row=i,column=3)
#self.title1.insert(0, title1)
#Second
title2 = 'paid' + str(i)
self.title2 = Tkinter.Entry(self,width=width)
self.title2.grid(row=i,column=4)
#self.title2.insert(0, title2)
#Third
title3 = 'received' + str(i)
self.title3 = Tkinter.Entry(self,width=width)
self.title3.grid(row=i,column=5)
#self.title3.insert(0, title3)
## Methods
def fillWindow(self):
global fileDirectory
location = os.path.join(fileDirectory, family + '.txt')
file = open(location, 'r')
ordersDict = {}
for line in file:
(key, value) = line.split(':', 1)
ordersDict[key] = value
for key in ordersDict:
ordersDict[key] = ordersDict[key][:-2]
for item in ordersDict:
if item[0] == '#':
if item[1] == 'o':
self.name = 'ordered%s' %item[2:]
self.name.insert(0,ordersDict[item])
fillWindow(self)
It looks like you have a conceptual error there: inside this method, the variable "name" does not exist up to the last line on the first listing. Then it is created, and points to an ordinary Python string -- if you are using a "name" variable elsewhere on your class that variable does not exist inside this method.
For an easy fix of your existing code, try calling the variable as "self.name" instead of just name where it is created, and on your last line in this method use:
self.name.insert(0,ordersDict[item]) instead.
The self. prefix will turn your variable into an instance variable, which is shared across methods on the same instance of the class.
On a side note, you don' t need even the dictionary much less three consecutive for loops on this method, just insert the relevant values you extract from "line" in your text variable.

Categories

Resources