Advice on combining or coordinating multiple python scripts - python

I am still somewhat of a Python novice and am working on a raspberrypi based project at the moment.
I have successfully created and tested two (fairly simple) scripts which work well independently.
Script 1: continually scans for specific BLE devices and decodes the manufacturer data from the advert.
Script 2: continually reads data from a html page and decodes.
The raspberrypi passes all of the relevant information onto an HMI via a RS232 serial link. The HMI is limited in the fact it needs to receive all of the information from both scripts in the same message so I need to repeatedly send a data string with all of the info in. Script 2 contributes the first two parts of the string, script 2 contributes the remaining 20 parts of the string.
As you can see, the scripts currently have a small section at the end which sends the serial data from that script.
As I want to prevent too much lag between the info being received and processed and cannot predict when the data will be received, I don't think combining into a single large file will work as I will end up potentially missing data (e.g. the BLE data being sent). So I am assuming I need to run both scripts in the background and keep updating the relevant variables internally, then running a third script which reads them and collates them and sends the serial data?
Script 1:
`#! /usr/bin/python3 -u
import serial
import struct
from time import *
from bluepy.btle import Scanner
ser = serial.Serial('/dev/ttyS0',9600) #define serial port (PiZero
onboard UART)
coding = "Windows-1252"
SENSORS = {"80:ea:ca:12:23:0b": "Front Left Tyre:" ,"81:ea:ca:22:20:f7" : "Front Right Tyre:", "82:ea:ca:32:24:87" : "Rear Left Tyre:", "83:ea:ca:42:23:07" : "Rear Right Tyre:"}
scanner = Scanner()
#set starting values for all output variables
pres_fl = pres_fr = pres_rl = pres_rr = ""
temp_fl = temp_fr = temp_rl = temp_rr = ""
batt_fl = batt_fr = batt_rl = batt_rr = ""
status_fl = status_fr = status_rl = status_rr = "NONE"
flat_fl = flat_fr = flat_rl = flat_rr = "00"
front_min_pres = 30 # minimum pressure front psi
rear_min_pres = 30 # minimum pressure rear psi
max_temp = 50 # maximum temperature degC
min_batt = 30 # minimum battery level %
max_loss = 5
fl_count = 0
fr_count = 0
rl_count = 0
rr_count = 0
def sort_data(input_data):
#read the relevant bytes fromt he array to each parameter
id_byte = chunks[2:8]
pres_byte = chunks[8:12]
temp_byte = chunks[12:16]
batt_byte = chunks[16]
flat_byte = chunks[17]
#join the elements of each of the sub-arrays into a string
id_str = ''.join(id_byte)
pres_str = ''.join(pres_byte)
temp_str = ''.join(temp_byte)
#convert strings into bytes from hex
pres_hex = bytes.fromhex(pres_str)
temp_hex = bytes.fromhex(temp_str)
#convert each bytes into integers
pres_int = int.from_bytes(pres_hex,'little')
temp_int = int.from_bytes(temp_hex,'little', signed=True)
batt_int = int(batt_byte, 16)
#convert into strings and do necessary unit conversions
pres = str(round(((pres_int/100000)*14.5),1))
temp = str(round((temp_int/100),1))
batt = str(batt_int)
return (id_str , pres , temp , batt , flat_byte)
def check(input_pres,input_temp,input_batt):
input_pres = float(input_pres)
input_temp = float(input_temp)
input_batt = float(input_batt)
if "Front" in device_location:
if input_pres <= front_min_pres:
status = "LOW PRESSURE"
elif input_temp >= max_temp:
status = "HIGH TEMP"
elif input_batt <= min_batt:
status = "LOW BATTERY"
else:
status = "OKAY"
elif "Rear" in device_location:
if input_pres <= rear_min_pres:
status = "LOW PRESSURE"
elif input_temp >= max_temp:
status = "HIGH TEMP"
elif input_batt <= min_batt:
status = "LOW BATTERY"
else:
status = "OKAY"
return status
while True:
scan_entries = scanner.scan(2.0)
#Scan for listed BLE devices and retrieve manufacturer info
for scan_entry in scan_entries:
if scan_entry.addr in SENSORS:
device_location = SENSORS[scan_entry.addr]
manufacturer_hex = next(value for _, desc, value in
scan_entry.getScanData() if desc == 'Manufacturer')
manufacturer_bytes = bytes.fromhex(manufacturer_hex)
# Move manufacturer info into an array of x00 chunks
chunk_length = 2
chunks = [manufacturer_hex[i:i+chunk_length] for i in range(0, len(manufacturer_hex), chunk_length)] # combine data into an array
id_str , pres , temp , batt , flat_byte = sort_data(chunks)
if flat_byte == "00":
if id_str == "80eaca12230b":
fl_count = 0
position = "FL Tyre"
pres_fl = pres
temp_fl = temp
batt_fl = batt
status_fl = check(pres,temp,batt)
flat_fl = flat_byte
fr_count = fr_count + 1
if fr_count >= max_loss:
status_fr = "LOST"
rl_count = rl_count + 1
if rl_count >= max_loss:
status_rl = "LOST"
rr_count = rr_count + 1
if rr_count >= max_loss:
status_rr = "LOST"
elif id_str == "81eaca2220f7":
fr_count = 0
position = "FR Tyre"
pres_fr = pres
temp_fr = temp
batt_fr = batt
status_fr = check(pres,temp,batt)
flat_fr = flat_byte
fl_count = fl_count + 1
if fl_count >= max_loss:
status_fl = "LOST"
rl_count = rl_count + 1
if rl_count >= max_loss:
status_rl = "LOST"
rr_count = rr_count + 1
if rr_count >= max_loss:
status_rr = "LOST"
elif id_str == "82eaca322487":
rl_count = 0
position = "RL Tyre"
pres_rl = pres
temp_rl = temp
batt_rl = batt
status_rl = check(pres,temp,batt)
flat_rl = flat_byte
fl_count = fl_count + 1
if fl_count >= max_loss:
status_fl = "LOST"
fr_count = fr_count + 1
if fr_count >= max_loss:
status_fr = "LOST"
rr_count = rr_count + 1
if rr_count >= max_loss:
status_rr = "LOST"
elif id_str == "83eaca422307":
rr_count = 0
position = "RR Tyre"
pres_rr = pres
temp_rr = temp
batt_rr = batt
status_rr = check(pres,temp,batt)
flat_rr = flat_byte
fl_count = fl_count + 1
if fl_count >= max_loss:
status_fl = "LOST"
fr_count = fr_count + 1
if fr_count >= max_loss:
status_fr = "LOST"
rl_count = rl_count + 1
if rl_count >= max_loss:
status_rl = "LOST"
trip_ser = bytes("TRIP NAME," + "TRIP VALUE,", coding)
pres_ser = bytes(pres_fl + "," + pres_fr + "," + pres_rl + "," + pres_rr + ",", coding)
temp_ser = bytes(temp_fl + "," + temp_fr + "," + temp_rl + "," + temp_rr + ",", coding)
batt_ser = bytes(batt_fl + "," + batt_fr + "," + batt_rl + "," + batt_rr + ",", coding)
flat_ser = bytes(flat_fl + "," + flat_fr + "," + flat_rl + "," + flat_rr + ",", coding)
status_ser = bytes(status_fl + "," + status_fr + "," + status_rl + "," + status_rr, coding)
terminator = bytes("\r", coding)
textstr = trip_ser + pres_ser + temp_ser + batt_ser + flat_ser + status_ser + terminator
ser.write(textstr)
print(textstr.decode(coding))
print("FL:" + str(fl_count))
print("FR:" + str(fr_count))
print("RL:" + str(rl_count))
print("RR:" + str(rr_count))
sleep(0)
else:
status = "PUNCTURE"
if id_str == "80eaca12230b":
position = "FL Tyre"
pres_fl = pres
temp_fl = temp
batt_fl = batt
status_fl = status
flat_fl = flat_byte
elif id_str == "81eaca2220f7":
position = "FR Tyre"
pres_fr = pres
temp_fr = temp
batt_fr = batt
status_fr = status
flat_fr = flat_byte
elif id_str == "82eaca322487":
position = "RL Tyre"
pres_rl = pres
temp_rl = temp
batt_rl = batt
status_rl = status
flat_rl = flat_byte
elif id_str == "83eaca422307":
position = "RR Tyre"
pres_rr = pres
temp_rr = temp
batt_rr = batt
status_rr = status
flat_rr = flat_byte
trip_ser = bytes(",,", coding) # **These two parts need to come from script 2**
pres_ser = bytes(pres_fl + "," + pres_fr + "," + pres_rl + "," + pres_rr + ",", coding)
temp_ser = bytes(temp_fl + "," + temp_fr + "," + temp_rl + "," + temp_rr + ",", coding)
batt_ser = bytes(batt_fl + "," + batt_fr + "," + batt_rl + "," + batt_rr + ",", coding)
flat_ser = bytes(flat_fl + "," + flat_fr + "," + flat_rl + "," + flat_rr + ",", coding)
status_ser = bytes(status_fl + "," + status_fr + "," + status_rl + "," + status_rr + ",", coding)
terminator = bytes("\r", coding)
textstr = trip_ser + pres_ser + temp_ser + batt_ser + flat_ser + status_ser + terminator
ser.write(textstr)
print(textstr.decode(coding))
`
Script 2
#! /usr/bin/python3 -u
import urllib.request , time , serial
ser = serial.Serial('/dev/ttyS0',9600)
#List of Charactors to remove from the message
bad_chars = ['{' , '":' , ' "' , '}' , '"']
format = "Windows-1252"
#-----------------Functions----------------------------
#Decode the incoming serial datastream
def decode_serial(input1):
output1 = input1.decode(format).replace('\r','').replace('\n','') #decode the data and remove the \n & \n charactors
return (output1)
#Convert fuel economy value to mpg
def convert_economy(input2):
input2 = float(input2)
output2 = round((input2 * 282.481),1)
output2 = str(output2)
return (output2)
#Convert speed value to mph
def convert_speed(input3):
input3 = float(input3)
output3 = round((input3 * 0.6214))
output3 = str(output3)
return (output3)
#Convert KPa value to bar
def convert_pres(input5):
input5 = float(input5)
output5 = (input5 / 100)
output5 = str(output5)
return (output5)
#------------------Main Program----------------------------
while True:
# If there is a connection to the host:
try:
data = urllib.request.urlopen("http://192.168.4.1/readVal").read()
#turn data into a string
decode = data.decode()
#remove bad characters from string
for i in bad_chars:
decode = decode.replace(i,'')
#split into list (comma seperated)
list = decode.split(",")
#assign to each type
name_raw = list[0]
value_raw = list[1]
unit_raw = list[2]
#remove superflous characters
name = name_raw.replace("n","", 1)
value = value_raw.replace("v","")
value = value.replace('<br />'," ")
unit = unit_raw.replace("u","")
#Carry out name , value & unit conversion if Turbo Boost is received
if name == 'Turbo boost':
name = 'Turbo Boost'
unit = 'bar'
value = convert_pres(value)
#If no unit is provided then ignore addition of unit
if unit == '':
name = name
#If unit is HTML temperature character then replace with UTF-8 DegC
elif unit == '°C':
subunit = '\u00b0' + "C"
name = name + ' (' + subunit + ')'
#Carry out unit and value conversion if Speed is received
elif unit == 'km/h':
subunit = 'mph'
name = name + ' (' + subunit + ')'
value = convert_speed(value)
#Carry out unit and value conversion if Consumption is received
elif unit == 'l/100':
subunit = 'mpg'
name = name + ' (' + subunit + ')'
value = convert_economy(value)
#Combine name and unit into name string
else:
name = name + ' (' + unit + ')'
# Combine data to send as bytes via RS232 Comms
textstr = bytes(name + ',' + value + "\r",format) #**This is where script 1 would contribute the remaining parts**
ser.write(textstr)
(EXCUSE THE WONKY INDENTING, pasting in my code from notepad++ didnt work smoothly this time)
I am unsure whether I can create another script just for the serial communication which reads the current variables from the two scripts periodically as they internally change or not? I have only previously defined functions within one script and called them from another or just variables which remain fixed (not constantly changing like these).

My approach would be to use multithreading. It sounds scary, but I think it is the cleanest way to run 2 loops at the same time.
I am quite new with python so I can't really help you with exact solution. But I hope my idea could help you at least a little bit
The idea is that you run script1 and script2 as secondary threads and append the outputs from them to main thread into lists.
Then the main thread combines the information and sends it to HMI.
This will work if the script 1 and 2 send information with the same frequency. If they don't you can adjust it in the main loop
import threading
data_1 = []
data_2 = []
def script_1():
while True:
# do something - your script 1
# create textstr
data_1.append(textstr)
def script_2():
while True:
# do something - your script 2
# create textstr
data_2.append(textstr)
# Create threads
thread_1 = threading.Thread(target=script_1)
thread_2 = threading.Thread(target=script_2)
# Start threads (never ending while loops)
thread_1.start()
thread_2.start()
# Main loop
while True:
if len(data_1) > 0 and len(data_2) > 0:
# Combine data and send them to HMI
combined_data = data_1[0] + data_2[0]
send_to_HMI(combined_data)
# Remove sent data from lists
data_1.pop(0)
data_2.pop(0)
Also this is probably very bad performance-wise. There are better ways to do this, but this is the only one I know about.

Related

How can I display max number of loses from this dataframe in Pandas?

I wrote a webscraper which is downloading table tennis data. There is info about players, match score etc. I would like to display players which lost the most matches per day. I've created data frame and I would like to sum p1_status and p2_status, then I would like to display Surname and number of loses next to player.
https://gyazo.com/19c70e071db78071e83045bfcea0e772
Here is my code:
s = Service("D:/setka/chromedriver.exe")
option = webdriver.ChromeOptions()
driver = webdriver.Chrome(service=s)
hall = 10
num =1
filename = "C:/Users/filip/result2.csv"
f=open(filename,"w")
headers = "p1_surname, p1_name, p1_score, p2_surname, p2_name, p2_score, p1_status, p2_status \n"
f.write(headers)
while hall <= 10:
for period in [1]:
url = 'https://tabletennis.setkacup.com/en/schedule?date=2021-12-04&hall=' + \
str(hall) + '&' + 'period=' + str(period)
driver.get(url)
time.sleep(5)
divs = driver.find_elements(By.CSS_SELECTOR, "div.score-result")
for div in divs:
data = div.text.split()
#print(data)
if(num % 2) == 0:
f.write(str(data[0]) + "," + str(data[1]) + "," + str(data[2] + "," + "\n"))
else:
f.write(str(data[0]) + "," + str(data[1]) + "," + str(data[2] + ","))
num = num +1
hall =hall + 1
f.close()
df_results=pd.read_csv('C:/Users/filip/result2.csv', sep = r',',
skipinitialspace = True)
df_results.reset_index(drop=True, inplace=True)
df_results.loc[df_results['p1_score'] > df_results['p2_score'], ['p1_status','p2_status']] = ['won','lost']
df_results.loc[df_results['p1_score'] < df_results['p2_score'], ['p1_status','p2_status']] = ['lost','won']
df_results.loc[df_results['p1_score'] == df_results['p2_score'], ['p1_status','p2_status']] = ['not played','not played']
df_results.loc[((df_results['p1_score'] < 3) & (df_results['p1_score']!=0) & (df_results['p2_score'] <3) & (df_results['p2_score']!=0)), ['p1_status','p2_status']] = ['inplay','inplays']
df_results.loc[df_results['p1_status'] != df_results['p2_status'], ['match_status']] = ['finished']
df_results.loc[df_results['p1_status'] == df_results['p2_status'], ['match_status']] = ['not played']
df_results.loc[((df_results['p1_status'] =='inplay') & (df_results['p2_status']=='inplays')), ['match_status']] = ['inplay']
df_results = df_results.dropna(axis=1)
df_results.head(30)
Split your dataframe in 2 parts (p1_, p2_) to count defeats of each player then merge them:
Setup a MRE:
df = pd.DataFrame({'p1_surname': list('AABB'), 'p2_surname': list('CDCD'),
'p1_status': list('LWWW'), 'p2_status': list('WLLL')})
print(df)
# Output:
p1_surname p2_surname p1_status p2_status
0 A C L W
1 A D W L
2 B C W L
3 B D W L
>>> pd.concat([
df.filter(like='p1_').set_index('p1_surname')['p1_status'].eq('L').rename('loses'),
df.filter(like='p2_').set_index('p2_surname')['p2_status'].eq('L').rename('loses')]) \
.groupby(level=0).sum().rename_axis('surname').reset_index()
surname loses
0 A 1
1 B 0
2 C 1
3 D 2

Python function to format output record and write to file is not working

A client requires output in a specific format. I have a pipe delimited file with 4 fields as input; note id, note date, note user, note text. The input note text can be anywhere from 10 characters to 150 characters. The logic to format the output record requires inserting a caret (^) at a word break at or before 72 characters up to a maximum overall field length of 1981 characters. The logic also requires separate output records by date. Rather than repeat the rather involved coding I want to use a function to format and write the output record, but it keeps failing and I am stumped.
The error message is:
Unhandled exception while debugging...
Traceback (most recent call last):
File "C:\Python37\test_scripts\Outbound_Notes.py", line 137, in <module>
Output_Note(hold_note)
File "C:\Python37\test_scripts\Outbound_Notes.py", line 49, in Output_Note
y = len(hold_word[i])
IndexError: list index out of range
Here is my script
import string
import sys
import os
# hard codedd file-names for testing.
ifilename = 'TEST_INPUT.DAT'
ofilename = 'TEST_OUTPUT.TXT'
#ifilename = sys.argv[1].replace("\\", "/")
#ofilename = sys.argv[2].replace("\\", "/")
acctNbrOutput = False
hold_id = ''
def Output_Note(note_text):
maxnote1 = 72
maxnote2 = 1981
i = 0
w = 0
y = 0
z = 0
hold_word = note_text.split()
word_count = len(note_text.split())
temp_note = hold_user
z = 6
w = 6
while i <= word_count:
y = len(hold_word[i])
w = w + y
if w < maxnote2:
w = w + 1
z = z + 1
if (z + y) < maxnote1:
temp_note = temp_note + " " + hold_word[i]
z = z + y
elif (z + y) >= maxnote1:
temp_note = temp_note + "^" + hold_word[i]
z = y
# end if
else:
noteRecord = '12001' + hold_date + ' ' + temp_note + '\n'
outputRecord = noteRecord
f2.write(outputRecord)
temp_note = hold_user
z = 6
w = 6
temp_note = temp_note + " " + hold_word[i]
z = z + y
w = w + y
# end if
i = i + 1
# end while loop
if temp_note != hold_user:
noteRecord = '12001' + hold_date + ' ' + temp_note + '\n'
outputRecord = noteRecord
f2.write(outputRecord)
# end if
with open(ifilename, 'r') as f1:
f1.seek(0) #ensure you're at the start of the file..
first_char = f1.read(1) #get the first character
if not first_char:
print("file is empty") #first character is the empty string.
open(ofilename, "w+").close()
else:
f1.seek(0) #first character wasn't empty, return to start of file.
with open(ofilename, 'w') as f2:
# maxnote1 = 72
# maxnote2 = 1981
# loop through each record in the notes input file
for line in f1:
line = line.strip()
split_note = line.split('|')
note_id = split_note[0]
note_date = split_note[1]
note_user = split_note[2]
note_text = split_note[3]
# When the first note is read, initialize the hold fields.
if not hold_id:
print(hold_id)
hold_id = note_id
hold_date = note_date
hold_user = note_user
hold_note = note_text
acctRecord = '10001' + str(hold_id).zfill(10) + '\n'
outputRecord = acctRecord
f2.write(outputRecord)
acctNbrOutput = True
# If the notes have all been read for the patient
elif hold_id != note_id:
if not acctNbrOutput:
acctRecord = '10001' + str(hold_id).zfill(10) + '\n'
outputRecord = acctRecord
f2.write(outputRecord)
acctNbrOutput = True
# end if
Output_Note(hold_note)
outputRecord = '19999' + '\n'
f2.write(outputRecord)
hold_id = note_id
hold_date = note_date
hold_user = note_user
hold_note = note_text
acctRecord = '10001' + str(hold_id).zfill(10) + '\n'
outputRecord = acctRecord
f2.write(outputRecord)
acctNbrOutput = True
# If file contains notes from multiple dates
elif hold_date != note_date:
if not acctNbrOutput:
acctRecord = '10001' + str(hold_id).zfill(10) + '\n'
outputRecord = acctRecord
f2.write(outputRecord)
acctNbrOutput = True
# end if
Output_Note(hold_note)
hold_date = note_date
hold_note = note_text
else:
hold_note = hold_note + ' ' + note_text
# end if
# end for loop
if not acctNbrOutput:
acctRecord = '10001' + str(hold_id).zfill(10) + '\n'
outputRecord = acctRecord
f2.write(outputRecord)
acctNbrOutput = True
# end if
Output_Note(hold_note)
outputRecord = '19999' + '\n'
f2.write(outputRecord)
outputRecord = '**END'
f2.write(outputRecord)
# end if
#end if
Always try to minimize your code to only feature your error. In your case, the error appears in the line
y = len(hold_word[i])
Collecting the stuff neccessary to have everything defined here, gives you this:
note_text = "Some example line\n" #I have no idea what your input might look like
hold_word = note_text.split()
word_count = len(note_text.split())
while i <= word_count:
y = len(hold_word[i])
i=i+1
This is all the code neccessary to reproduce your error! Now its time to check the error message: **IndexError: list index out of range**, so it seems like the index i to access the list gets too large. With the minimal example, we can quickly tell what the largest possible value of i is, since i<=word_count and word_count = len(note_text.split()), the largest value of i is len(note_text.split()), but the largest index in the list is len(note_text.split()) - 1, so change your condition in the while to make sure that the index is smaller than the lebgth always:
note_text = "Some example line\n"
hold_word = note_text.split()
word_count = len(note_text.split())
while i < word_count: #Note, now < instead of <=
y = len(hold_word[i])
i=i+1
Notes:
1) Don't repeat yourself, you are doing note_text.split() twice, better write:
hold_word = note_text.split()
word_count = len(hold_word)
2) As far as I can see, you are only using i to access the list at an index, so you could change your while loop into a for loop:
for word in hold_word
and then use word instead of hold_word[i]

Unable to select date from datepicker calendar in selenium using python

I'd like to use python selenium to search at https://book.spicejet.com/Search.aspx
I reviewed this question but it is not the right answer what I am looking for.
I searched for a flight from Kolkata to Goa with 2 adults and 2 Infants. When I am giving passenger details I couldn't able to select infants Date of birth.
import time
import selenium
from selenium import webdriver
from selenium.webdriver.support.ui import Select
browser = webdriver.Chrome()
booking_url = "https://book.spicejet.com/Search.aspx"
browser.get(booking_url)
departureButton = browser.find_element_by_id("ControlGroupSearchView_AvailabilitySearchInputSearchVieworiginStation1_CTXT").click()
browser.find_element_by_partial_link_text("Kolkata").click()
arivalButton = browser.find_element_by_id("ControlGroupSearchView_AvailabilitySearchInputSearchViewdestinationStation1_CTXT")
arivalButton.click()
time.sleep(.3)
arivalButton.send_keys("Goa")
time.sleep(1)
search_date = "20-September 2019"
dep_date = search_date.split("-")
dep_month = dep_date[1]
dep_day = dep_date[0]
while browser.find_element_by_class_name("ui-datepicker-title").text != dep_month:
browser.find_element_by_css_selector("a[title='Next']").click()
browser.find_element_by_xpath("//table//a[text()='"+dep_day+"']").click()
time.sleep(1)
try:
return_date_close = browser.find_element_by_class_name("date-close").click
except:
pass
pax_selct = browser.find_element_by_id("divpaxinfo").click()
time.sleep(.2)
# __________Adult number_____________
for i in range(0, 2 - 1):
adults = browser.find_element_by_id("hrefIncAdt")
adults.click()
# ____________Set Num of Children___________________
for i in range(0, 0):
childrens = browser.find_element_by_id("hrefIncChd")
childrens.click()
# ____________Set Num of Infant(s)___________________
for i in range(0, 2):
infants = browser.find_element_by_id("hrefIncInf")
infants.click()
donebttn = browser.find_element_by_id("btnclosepaxoption").click()
searchBtn = browser.find_element_by_class_name("bookbtn").click()
browser.switch_to.default_content()
flightarr = []
tbl_row = browser.find_elements_by_class_name("fare-row")
time_select=3
price_select=1
new_time_serial = 0
tr_cont = 4
for item in tbl_row:
if item.is_displayed():
if new_time_serial == time_select:
col = item
cont = str(tr_cont)
if price_select == 0:
price1 = col.find_element_by_xpath('//*[#id="availabilityTable0"]/tbody/tr['+cont+']/td[3]/p').click()
elif price_select == 1:
price2 = col.find_element_by_xpath('//*[#id="availabilityTable0"]/tbody/tr['+cont+']/td[4]/p').click()
new_time_serial = new_time_serial + 1
tr_cont = tr_cont + 1
time.sleep(1)
cntn_btn = browser.find_element_by_class_name("button-continue").click()
passen_serial = 0
passen_serial_inf = 0
#inf = 1
birth_year = "2017"
birth_month = "Nov"
birth_day = "30"
all_pass_frm = browser.find_element_by_class_name("multicontent")
all_pass_entry = all_pass_frm.find_elements_by_class_name("sectionContent")
for passen in all_pass_entry:
pass_type = passen.find_element_by_class_name("guest-heading").text.split(' ',1)[0]
pass_type2 = passen.find_element_by_class_name("guest-heading").text.split(' ',1)[1]
if pass_type == "Adult":
deg_sel_name = Select(passen.find_element_by_id("CONTROLGROUPPASSENGER_PassengerInputViewPassengerView_DropDownListTitle_" + str(passen_serial) + ""))
deg_sel_name.select_by_index(1)
first_name_in = passen.find_element_by_id("CONTROLGROUPPASSENGER_PassengerInputViewPassengerView_TextBoxFirstName_" + str(passen_serial) + "")
first_name_in.send_keys("imam")
last_name_in = passen.find_element_by_id("CONTROLGROUPPASSENGER_PassengerInputViewPassengerView_TextBoxLastName_" + str(passen_serial) + "")
last_name_in.send_keys("Hossain")
elif pass_type == "Child":
deg_sel_name = Select(passen.find_element_by_id("CONTROLGROUPPASSENGER_PassengerInputViewPassengerView_DropDownListGender_" + str(passen_serial) + ""))
deg_sel_name.select_by_index(2)
first_name_in = passen.find_element_by_id("CONTROLGROUPPASSENGER_PassengerInputViewPassengerView_TextBoxFirstName_" + str(passen_serial) + "")
first_name_in.send_keys("Korim")
last_name_in = passen.find_element_by_id("CONTROLGROUPPASSENGER_PassengerInputViewPassengerView_TextBoxLastName_" + str(passen_serial) + "")
last_name_in.send_keys("Hossain")
elif pass_type == "Infant":
deg_sel_name = Select(passen.find_element_by_id("CONTROLGROUPPASSENGER_PassengerInputViewPassengerView_DropDownListGender_"+ str(passen_serial_inf) + "_" + str(passen_serial_inf) + ""))
deg_sel_name.select_by_index(2)
first_name_in = passen.find_element_by_id("CONTROLGROUPPASSENGER_PassengerInputViewPassengerView_TextBoxFirstName_"+ str(passen_serial_inf) + "_" + str(passen_serial_inf) + "")
first_name_in.send_keys("Aqiba")
last_name_in = passen.find_element_by_id("CONTROLGROUPPASSENGER_PassengerInputViewPassengerView_TextBoxLastName_"+ str(passen_serial_inf) + "_" + str(passen_serial_inf) + "")
last_name_in.send_keys("Hassan")
dob = passen.find_element_by_id("inputDateContactInfant" +str(pass_type2)+ "").click()
dob_cal = browser.find_element_by_class_name("datepickerViewYears")
dob_cal_year = dob_cal.find_element_by_class_name("datepickerYears")
inf_birth_year = dob_cal.find_element_by_xpath('.//*[#class="datepickerYears"]/tr/td/a/span[text()="'+birth_year+'"]').click()
inf_birth_mon = dob_cal.find_element_by_xpath('.//*[#class="datepickerMonths"]/tr/td/a/span[text()="'+birth_month+'"]').click()
inf_birth_day = dob_cal.find_element_by_xpath('.//*[#class="datepickerDays"]/tr/td/a/span[text()="'+birth_day+'"]').click()
# inf = inf +1
passen_serial_inf = passen_serial_inf + 1
passen_serial = passen_serial + 1
print("Done")
I tried with xPath it works for 1st infant but it is not working for 2nd infant. What should i need to do now? is there any way except XPath? And what can i do when passenger number is different?
I have extracted the var declarations and the var increments, there seems to be a mismatch at the declaration statements that could be causing the problem, don't the var declarations need to start at the same number? Set them equal and re-try.
var declaration
passen_serial_inf = 0
inf = 1
var increments
inf = inf +1
passen_serial_inf = passen_serial_inf + 1
passen_serial = passen_serial + 1

Nested while loop to extract text data

I am trying to get data from a txt file and put it into a dataframe. Text file looks something like this:
******************************************************************************************************************************
DATE BUY:2018/05/26
****************************************************************************************************************************
STORE: DUBIDUBI SAILOR: 123456
***********************************************************************************************************************
< CLIENT >
NAME CLIENT MEMBER TYPE MEMBER NUMBER: 89101112
ANTONY STARK 1
<PRODUCTS>
NUM-PRODUCTS
6
< ADDRESS TO SEND>
186 FLEET STREET
-----------------------------------------------------------------------------------------------------------------------
< CLIENT >
NAME CLIENT MEMBER TYPE MEMBER NUMBER: 13141516
THOR 2
<PRODUCTS>
NUM-PRODUCTS
2
< ADDRESS TO SEND>
1800 PENNSYLVANIA STREET
<SERVICES>
NUM-SERVICE TYPE OF SERVICE
64 DEVOLUTION
*****************************************************************************************************************************
I want to get a dataframe containing a list of all the clients information that were assisted by same sailor in same store.
What does works: below code reads the text line by line and extract the information of each line.
data []
global STORE, DATE_BUY, SAILOR, CLIENT, MEMBER_NUM, NUM_PRODUCTS, ADDRESS, NUM_SERVICE, TYPE_MEMB, TYPE_SERV
STORE = ""
DATE_BUY = ""
SAILOR = ""
CLIENT = ""
MEMBER_NUM = ""
NUM_PRODUCTS = ""
ADDRESS = ""
NUM_SERVICE = ""
TYPE_MEMB = ""
TYPE_SERV = ""
with open ('myfile', 'r') as txt_file:
read_file = txt_file.readlines()
for i in range(0, len(read_file)):
line = read_file[i]
z = line[0:50]
a = line[0:9]
b = line[0:42]
c = line[112:132]
d = line[0:14]
e = line[0:14]
dif_client = line[0:58]
if a == " STORE":
STORE = line[10:28]
SAILOR = line[30:45]
elif c == " DATE BUY":
DATE_BUY = line[133:145]
elif b == " NAME CLIENT"
nextline = read_file[i + 1]
CLIENT = nextline[0:57]
MEMBER_NUM = nextline[96:126]
TYPE_MEMB = nextline[79:86]
elif d == " < ADDRESS":
nextline = read_file[i + 1]
ADDRESS = nextline[0:63]
elif e == " < PRODUCTS":
nextline = read_file[i + 1]
NUM_PRODUCTS = nextline[0:24]
elif f == " <SERVICES":
nextline = read_file[i + 1]
NUM_SERVICE = nextline[]
TYPE_SERV = nextline[]
data.append({'Store':STORE, 'Sailor':SAILOR, 'Date_Buy':DATE_BUY, 'Client':CLIENT, 'Member_Num':MEMBER_NUM,
'Type_Memb':TYPE_MEMB, 'Address':ADDRESS, 'Products':NUM_PRODUCTS,'Num_Serv':NUM_SERVICE, 'Type_Serv':TYPE_SERV})
df = pd.DataFrame(data)
What does NOT works: when using a nested while loop to extract information of each client assisted by a sailor my code simply does not end running. The code that does not work is:
data []
global STORE, DATE_BUY, SAILOR, CLIENT, MEMBER_NUM, NUM_PRODUCTS, ADDRESS, NUM_SERVICE, TYPE_MEMB, TYPE_SERV
STORE = ""
DATE_BUY = ""
SAILOR = ""
CLIENT = ""
MEMBER_NUM = ""
NUM_PRODUCTS = ""
ADDRESS = ""
NUM_SERVICE = ""
TYPE_MEMB = ""
TYPE_SERV = ""
with open ('myfile', 'r') as txt_file:
read_file = txt_file.readlines()
for i in range(0, len(read_file)):
line = read_file[i]
z = line[0:50]
a = line[0:9]
b = line[0:42]
c = line[112:132]
d = line[0:14]
e = line[0:14]
dif_client = line[0:58]
while dif_client != " < CLIENT >":
if a == " STORE":
STORE = line[10:28]
SAILOR = line[30:45]
elif c == " DATE BUY":
DATE_BUY = line[133:145]
elif b == " NAME CLIENT"
nextline = read_file[i + 1]
CLIENT = nextline[0:57]
MEMBER_NUM = nextline[96:126]
TYPE_MEMB = nextline[79:86]
elif d == " < ADDRESS":
nextline = read_file[i + 1]
ADDRESS = nextline[0:63]
elif e == " < PRODUCTS":
nextline = read_file[i + 1]
NUM_PRODUCTS = nextline[0:24]
elif f == " <SERVICES":
nextline = read_file[i + 1]
NUM_SERVICE = nextline[]
TYPE_SERV = nextline[]
data.append({'Store':STORE, 'Sailor':SAILOR, 'Date_Buy':DATE_BUY, 'Client':CLIENT, 'Member_Num':MEMBER_NUM,
'Type_Memb':TYPE_MEMB, 'Address':ADDRESS, 'Products':NUM_PRODUCTS,'Num_Serv':NUM_SERVICE, 'Type_Serv':TYPE_SERV})
df = pd.DataFrame(data)
The desired output should look something like this. I know that each client information comes when the word < CLIENT > appears in text.
Date_buy Store Sailor Client Member_Number Num_Products Address_to_send num_Service type_serv
2018/05/26 dubidubi 123456 ANTONY STARK 89101112 6 186 FLEET STREET
2018/05/26 dubidubi 123456 THOR 13141516 2 1800 PENNSYLVANIA STREET 64 DEVOLUTION
Thanks for the description. The problem is in the infinite loop you built:
dif_client = line[0:58]
while dif_client != " < CLIENT >":
if a == " STORE":
...
dif_client doesn't change within the loop. There is no break or other exit, only the while condition (which is good design). Therefore, once you get into the loop, you have no way to leave: dif_client is constant.
Your logic is incorrect: you have two loops that are trying to walk through the lines of the file:
for i in range(0, len(read_file)):
...
while dif_client != " < CLIENT >":
# Process one line
The body of the while is designed to process one line. When you're done with that, you need to go to the next iteration of the for to get the next line. Finding a CLIENT line is a if decision, not a loop.

Python stange behaviour when acessing list elements

This small scripts makes exactly what I need.
#!/usr/bin/python
import os
import fileinput
import sys
import shutil
import glob
import time
def replaceAll1(files,searchExp,replaceExp):
for line in fileinput.input(files, inplace=1):
if searchExp in line:
line = line.replace(searchExp,replaceExp)
sys.stdout.write(line)
param1 = [1,2,3]
param2 = [1,2,3]
param3 = [1,2,3]
for i in xrange(len(param1)):
for ii in xrange(len(param2)):
for iii in xrange(len(param3)):
os.system("cp -a cold.in input.in")
old_param1 = "param1 = 1"
old_param2 = "param2 = 1"
old_param3 = "param3 = 1"
new_param1 = "param1 = " + str(param1[i])
new_param2 = "param2 = " + str(param2[ii])
new_param3 = "param3 = " + str(param3[iii])
replaceAll1('input.in',old_param1,new_param1)
replaceAll1('input.in',old_param2,new_param2)
replaceAll1('input.in',old_param3,new_param3)
time.sleep(4)
It enters in a configuration file and replaces sequentially the input parameters according to the lists that are accessed by the loop indexes. It is simple a combination of all the three parameters between each other.
# Input file
param1 = 1 # --- Should be [1,2,3]
param2 = 1 # --- Should be [1,2,3]
param3 = 1 # --- Should be [1,2,3]
The problem is that his big brother is not behaving like it. When it loops through the lists, it gets lost in scheme = 2 and puts dissp_scheme = 2 (freezed) when it should be dissp_scheme = 1. I printed out every single variable that goes inside the function replaceAll marked with comments but when I turn on the other calls it mess up everything. Here is the script.
#!/usr/bin/python
import os
import fileinput
import sys
import shutil
import glob
import time
os.chdir(os.getcwd())
# Replaces the input file parameters
def replaceAll(files,searchExp,replaceExp):
for line in fileinput.input(files, inplace=1):
if searchExp in line:
line = line.replace(searchExp,replaceExp)
sys.stdout.write(line)
# Gets a number inside my input file.
def get_parameter(variable,file_name):
f = open(file_name,'r').readlines()
for i in xrange(len(f)):
index = f[i].find(variable)
if index != -1:
pre_found = f[i].split('=')[1]
return pre_found
# Gets the discretization scheme name.
def get_sheme(number):
if number == 1:
return "Simple Centered Scheme"
elif number == 2:
return "Lax-Wendroff Scheme"
elif number == 3:
return "MacCormack Scheme"
elif number == 4:
return "Beam-Warming Scheme"
elif number == 5:
return "Steger-Warming 1st Order Scheme"
elif number == 6:
return "Steger-Warming 2nd Order Scheme"
elif number == 7:
return "Van Leer 1st Order Scheme"
elif number == 8:
return "Van Leer 2nd Order Scheme"
elif number == 9:
return "Roe Scheme"
elif number == 10:
return "AUSM Scheme"
# Gets the dissipation scheme name.
def get_dissip(number):
if number == 1:
return "Pullian Non-Linear dissipation"
elif number == 2:
return "Second difference dissipation"
elif number == 3:
return "Fourth difference dissipation"
elif number == 4:
return "B&W dissipation"
# Generates the density gnuplot scripts.
def gnuplot(variable,pressure_ratio,scheme,dissip_scheme):
#gnuplot('Density',10,get_sheme(3),'Pullian')
# Building name of the output file.
outFileName = variable.lower() + '_ratio' + str(int(pressure_ratio)) + '_' + scheme.replace(" ","") + '_dissp' + dissip_scheme.replace(" ","") + '.tex'
gnuFileName = variable.lower() + '_ratio' + str(int(pressure_ratio)) + '_' + scheme.replace(" ","") + '_dissp' + dissip_scheme.replace(" ","") + '.gnu'
# Build title of the plot
title = 'Analytical vs Numerical | ' + scheme
f = open(gnuFileName,'w')
f.write("set term cairolatex monochrome size 15.0cm, 8cm\n")
f.write('set output "' + outFileName + '"\n')
f.write("set grid\n")
f.write('set xtics font "Times-Roman, 10\n')
f.write('set ytics font "Times-Roman, 10\n')
f.write('set xlabel "x position" center\n')
f.write('set ylabel "' + variable + '" center\n')
f.write('set title "Analytical vs Numerical Results | ' + variable + '" \n')
f.write('set pointsize 0.5\n')
f.write('set key font ",10"\n')
fortran_out_analytical = 'a' + variable.lower() + '.out'
fortran_out_numerical = variable.lower() + 'Output.out'
f.write('plot "' + fortran_out_analytical +'" u 1:2 with linespoints lt -1 lw 1 pt 4 title "Analytical",\\\n')
f.write( '"' + fortran_out_numerical + '" u 1:2 with lines lw 5 title "Numerical"\n')
f.close()
# Generate latex code.
def generate_latex(text_image_file,caption):
latex.write("\\begin{figure}[H]\n")
latex.write(" \centering\n")
latex.write(" \input{" + text_image_file + "}\n")
latex.write(" \caption{"+ caption +"}\n")
latex.write(" \label{fig:digraph}\n")
latex.write("\\end{figure}\n")
latex.write("\n\n")
# -----------------------------------------------------------------------
# Main loop.
# -----------------------------------------------------------------------
pressure_ratios = [5.0]
schemes = [1,2,3]
dissips = [1,2,3]
# Define replace lines for replace all.
scheme_line = "scheme = "
dissip_line = "dissp_scheme = "
# Open Latex export file.
latex = open("bizu.txt",'w')
i = 0
# ratios.
for i in xrange(len(pressure_ratios)):
print "----------------------------------------"
print " + Configuring File for pressure ratio: " + str(pressure_ratios[i])
print "----------------------------------------\n"
# Schemes
for jj in xrange(len(schemes)):
print " + Configuring file for scheme: " + get_sheme(schemes[jj]) + "\n"
for kkk in xrange(len(dissips)):
print " + Configuring file for dissip: " + get_dissip(dissips[kkk])
# We always work with a brand new file.
os.system("rm input.in")
os.system("cp -a cold.in input.in")
# Replace pressures.
p1_line_old = 'p1 = 5.0d0'
rho1_line_old = 'rho1 = 5.0d0'
p1_line_new = 'p1 = ' + str(pressure_ratios[i]) + 'd0'
rho1_line_new = 'rho1 = ' + str(pressure_ratios[i]) + 'd0'
replaceAll('input.in',p1_line_old,p1_line_new)
replaceAll('input.in',rho1_line_old,rho1_line_new)
# Replace discretization scheme.
old_scheme = scheme_line + "1"
new_scheme = scheme_line + str(schemes[jj])
#==========================================================
# This call is messing everything up when scheme turns to 2
#==========================================================
replaceAll('input.in',old_scheme,new_scheme)
# Replace dissipation scheme.
old_dissp_scheme = dissip_line + "1"
new_dissp_scheme = dissip_line + str(dissips[kkk])
print p1_line_old
print new_scheme
print new_dissp_scheme
replaceAll('input.in',old_dissp_scheme, new_dissp_scheme)
time.sleep(3)
# ### Calling program
# os.system("./sod")
#
latex.close()
And the input file that the it works on is:
&PAR_physical
p1 = 5.0d0
p4 = 1.0d0
rho1 = 5.0d0
rho4 = 1.0d0
fgamma = 1.4d0
R_const = 287.0d0
F_Cp = 1004.5
F_Cv = 717.5
/
&PAR_geometry
total_mesh_points = 1001
start_mesh_point = -5.0d0
final_mesh_point = 5.0d0
print_step = 100
/
&PAR_numeric
scheme = 3
iterations = 10000
time_step = 0.0001d0
/
&PAR_dissip
dissp_scheme = 3
dissip_omega = 0.5d0
/
Thank you all !

Categories

Resources