Stuck in loop help - Python - python

The second 'if' statement midway through this code is using an 'or' between two conditions. This is causing the issue I just don't know how to get around it. The code is going through a data file and turning on the given relay number at a specific time, I need it to only do this once per given relay. If I use an 'and' between the conditions, it will only turn on the first relay that matches the current time and wait for the next hour and turn on the next given relay.
Could someone suggest something to fix this issue, thank you!
def schedule():
metadata, sched = dbx.files_download(path=RELAYSCHEDULE)
if not sched.content:
pass # If file is empty then exit routine
else:
relaySchedule = str(sched.content)
commaNum = relaySchedule.count(',')
data1 = relaySchedule.split(',')
for i in range(commaNum):
data2 = data1[i].split('-')
Time1 = data2[1]
currentRN = data2[0]
currentDT = datetime.datetime.now()
currentHR = currentDT.hour
global RN
global T
if str(currentHR) == str(Time1):
if T != currentHR or RN != currentRN:
relaynum = int(data2[0])
relaytime = int(data2[2])
T = currentHR
RN = currentRN
k = threading.Thread(target=SendToRelay(relaynum, relaytime)).start()
else:
print("Pass")
Desired Inputs:
sched.content = '1-19-10,3-9-20,4-9-10,'
T = ' '
RN = ' '
T and RN are global variables because the loop is running indefinitely, they're there to let the loop know whether the specific Time(T) and Relay Number(RN) have already been used.
Desired Outputs:
If the time is 9 AM then,
T = 9
RN should be whatever the given relay number is so RN = 3, but not sure this is the right thing to use.
Sorry if this is confusing. I basically need the program to read a set of scheduled times for specific relays to turn on, I need it to read the current time and if it matches the time in the schedule it will then check which relay is within that time and turn it on for however long. Once it has completed that, I need it to go over that same set of data in case there is another relay within the same time that also needs to turn on, the issue is that if I don't use T and RN variables to check whether a previous relay has been set, it will read the file and turn on the same relay over and over.

Try printing all used variables, check if everything is, what you think it is. On top of that, sometimes whietespaces characters causes problem with comparison.

I fixed it. For anyone wondering this is the new working code:
def schedule():
metadata, sched = dbx.files_download(path=RELAYSCHEDULE)
if not sched.content:
pass # If file is empty then exit routine
else:
relaySchedule = str(sched.content)
commaNum = relaySchedule.count(',')
data1 = relaySchedule.split(',')
for i in range(commaNum):
data2 = data1[i].split('-')
TimeSched = data2[1]
relaySched = data2[0]
currentDT = datetime.datetime.now()
currentHR = currentDT.hour
global RN
global T
if str(currentHR) == str(TimeSched):
if str(T) != str(currentHR):
RN = ''
T = currentHR
if str(relaySched) not in str(RN):
relaynum = int(data2[0])
relaytime = int(data2[2])
k = threading.Thread(target=SendToRelay(relaynum, relaytime)).start()
RN = str(RN) + str(relaySched)

Related

Code worked in coursera sandbox editor but fails in python 3

I am super new to Python. I've been taking a Python Course on Coursera and fooling around with a little bit of code. Prior to today I was doing the class on a chromebook, and therefore using the sandbox tool provided. I've purchased an actual PC to download python since. I wrote a little code that was working just fine in the sandbox tool, but when I enter it into python it keeps booting me out. Can anyone spot anything obviously wrong with my code that I should change?
It should take an input of a date, exercise, and then keep looping through asking you about your sets and reps, saving results as tuples in a dictionary, until you enter 0, where it exits the loop, and prints the results. Stumped!
dt = input("Date:")
ex = input("Exercise:")
d = dict()
set = 0
while True:
wrk = input("Insert as Reps x Weight: ")
if wrk == "0":
break
set = set + 1
d[set] = wrk
print(dt)
print(ex)
print(d)
Indentation is really important in Python since it uses whitespace to differentiate between blocks of code.
Here,
observe the indentation of the while statement. Note that the indentation in the if block remains the same. This is because we want break to execute only if wrk is 0.
On the other hand, we keep set+1 outside because the condition did not match and we wanted our program to keep running.
python
dt = input("Date:")
ex = input("Exercise:")
d = dict()
set = 0
while True:
wrk = input("Insert as Reps x Weight: ")
if wrk == "0":
break
set = set + 1
d[set] = wrk
print(dt)
print(ex)
print(d)
This works as expected.

Getting the results simultaneously from different sources

python newbie here!
I am trying to write a small program for myself which is basically getting price information from different exchanges and comparing them, so far it is working great but honestly, I want to make it better in terms of performance and efficiency.
What I mean by efficiency is my program is checking prices step by step and printing the results. My question is can I convert it to checking the prices simultaneously from different exchanges and print them all at the same time?
Below is the part of the code that I wrote:
#Novadax
symbol_novadax = coin_list[i] + "_USDT"
response_novadax = requests.get('https://api.novadax.com/v1/market/ticker?symbol=' + symbol_novadax)
novadax_dic = json.loads(response_novadax.content)
try:
if "ask" in novadax_dic["data"]:
novadax_bid_price = float(novadax_dic["data"]["bid"])
print("novadax_bid_price "+str(novadax_bid_price))
novadax_ask_price = float(novadax_dic["data"]['ask'])
print("novadax_ask_price " + str(novadax_ask_price))
if (max_bid_val < novadax_bid_price):
max_bid_val = novadax_bid_price
max_bid_place = "novadax"
if (min_ask_val > novadax_ask_price):
min_ask_val = novadax_ask_price
min_ask_place = "novadax"
except:
print(coin_list[i] + " not in novadax")
if is_run == False:
telegram_send.send(messages=["False novadax"], parse_mode=None)
break
#ZT
symbol_zt = coin_list[i] + "_USDT"
response_zt = requests.get('https://www.ztb.im/api/v1/tickers')
zt_dic = json.loads(response_zt.content)
# print(next(item for item in zt_dic["ticker"] if item["symbol"] == symbol_zt))
try:
if "buy" in next(item for item in zt_dic["ticker"] if item["symbol"] == symbol_zt):
zt_bid_price = float(next(item for item in zt_dic["ticker"] if item["symbol"] == symbol_zt)["buy"])
print("zt_bid_price "+str(zt_bid_price))
zt_ask_price = float(next(item for item in zt_dic["ticker"] if item["symbol"] == symbol_zt)['sell'])
print("zt_ask_price " + str(zt_ask_price))
if (max_bid_val < zt_bid_price):
max_bid_val = zt_bid_price
max_bid_place = "zt"
if (min_ask_val > zt_ask_price):
min_ask_val = zt_ask_price
min_ask_place = "zt"
except:
print(coin_list[i] + " not in zt")
if is_run == False:
telegram_send.send(messages=["False zt"], parse_mode=None)
break
my input is something like that:
zt_bid_price = 0.12
zt_ask_price = 0.14
novadax_bid_price = 0.13
novadax_ask_price= 0.14
To be more clear, I am not getting those results at the same time. I mean it prints in order and I am planning to add more exchanges in the future which means if I decide to print everything at the end of the code that will give me slightly old data. Does anyone have any idea about how can I solve this problem?
Thanks in advance!
Depending on your implementation you can use multi-processing to keep each ticker going. However there is overhead for each process which depending on your system, may or may not lag. You could have all the processes(tickers) running and either on a signal or on a time interval, have each simultaneously poll their source (with time stamp) and return their data.
There is a learning curve. The line below will get you started.
from multiprocessing import Pool

Lists not resetting after loop has been executed

I am trying create a loop that resets all the data inside of it every iteration but somewhere the data is not resetting even though I am initializing values inside of the loop.
Here is my code:
import time , sys , string
import serial
ser = serial.Serial("/dev/ttyUSB0", baudrate=9600,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS
)
print (ser.name)
ser.write(b'U')
#print ('test1')
time.sleep(2)
b=0
while (b <= 2):
time.sleep(0.25)
ser.write(b'R')
#print ('test2')
d = [] # establishes an empty list to iterate through all the incoming data
i=0 # beginning of the buffer
time.sleep(0.5)
while (i<=11):
d.append(str(ord(ser.read()))) #adding each incoming bit to the list
#print (d[i])
#print ('^ is the ' + str(i) + 'th term') // these two lines help establish where the useful information begins for the lidar.
i+=1
#establishing a better way to write the data out / gd = good distance
gd = []
a = 0
for a in range(8):
gd.append(str(chr(int(d[a+4]))))
print (gd)
print (gd[0] + gd[1] + gd[2] + gd[3] + gd[4] + gd[5] + gd[6] + gd[7] + ' mm')
ser.flush()
b+=1
The reason i do d[a+4] is because the first few bits of information are nonsense so I need it to start from that bit every time.
The program works in the first loop and correctly prints it out, however, in subsequent loops it begins to start from different points when I try to print out the values again. I am unsure if I am missing something and would love a second opinion.
My outputs are:
D = 0609 mm
\r:\rD = 0 mm
mm \r:\rD mm
so it's looping around the lists I'm creating somewhere and since it's taking in the string from the print statement I wonder if that has something to do with the issue.
I cannot add a comment, so here is a little suggestion. At the end of your main loop, after
b+=1
add the following line
d, gd = [], []
if they are no longer useful after the loop has ended (which I suspect is the case). It'll reset any value the both variables hold in them and you'll be able to start from empty lists again.

Stuff isn't appending to my list

I'm trying to create a simulation where there are two printers and I find the average wait time for each. I'm using a class for the printer and task in my program. Basically, I'm adding the wait time to each of each simulation to a list and calculating the average time. My issue is that I'm getting a division by 0 error so nothing is being appended. When I try it with 1 printer (Which is the same thing essentially) I have no issues. Here is the code I have for the second printer. I'm using a queue for this.
if printers == 2:
for currentSecond in range(numSeconds):
if newPrintTask():
task = Task(currentSecond,minSize,maxSize)
printQueue.enqueue(task)
if (not labPrinter1.busy()) and (not labPrinter2.busy()) and \
(not printQueue.is_empty()):
nexttask = printQueue.dequeue()
waitingtimes.append(nexttask.waitTime(currentSecond))
labPrinter1.startNext(nexttask)
elif (not labPrinter1.busy()) and (labPrinter2.busy()) and \
(not printQueue.is_empty()):
nexttask = printQueue.dequeue()
waitingtimes.append(nexttask.waitTime(currentSecond))
labPrinter1.startNext(nexttask)
elif (not labPrinter2.busy()) and (labPrinter1.busy()) and \
(not printQueue.is_empty()):
nexttask = printQueue.dequeue()
waitingtimes.append(nexttask.waitTime(currentSecond))
labPrinter2.startNext(nexttask)
labPrinter1.tick()
labPrinter2.tick()
averageWait = sum(waitingtimes)/len(waitingtimes)
outfile.write("Average Wait %6.2f secs %3d tasks remaining." \
%(averageWait,printQueue.size()))
Any assistance would be great!
Edit: I should mention that this happens no matter the values. I could have a page range of 99-100 and a PPM of 1 yet I still get divided by 0.
I think your problem stems from an empty waitingtimes on the first iteration or so. If there is no print job in the queue, and there has never been a waiting time inserted, you are going to reach the bottom of the loop with waitingtimes==[] (empty), and then do:
sum(waitingtimes) / len(waitingtimes)
Which will be
sum([]) / len([])
Which is
0 / 0
The easiest way to deal with this would just be to check for it, or catch it:
if not waitingtimes:
averageWait = 0
else:
averageWait = sum(waitingtimes)/len(waitingtimes)
Or:
try:
averageWait = sum(waitingtimes)/len(waitingtimes)
except ZeroDivisionError:
averageWait = 0

Python (Pywin32) Referencing Own Cell/Horizontal Movement

So please don't tell me to google or research or read anything, I've been doing that for the past couple of days and will get annoyed if I see someone say that again.
My problem: I am using pywin32 and python 2.7.8 to communicate with (an already existing) excel sheet. I use it to log my hours worked and money earned, etc. I have it functioning to the point that I can open the workbook, find the next empty cell under my existing entries and write the date in that cell. My problem lies in the fact that I need to navigate horizontally. I want the program to run automatically so I will not always know the number of the cell. For example, my current cell is 18,1. I need to move to 18,2 18,3 18,4 and 18,5. But next time I run the script I may need 19,2... etc.
How can I do this? Is there a way to return the current cell or something?
code:
import win32com.client as win32
import os, time
xl = win32.Dispatch('Excel.Application')
xl.visible = True
xl.Workbooks.Open(os.path.join('C:\\Users\\[REDACTED]\\Desktop', '[REDACTED].xls'))
xlSheet = xl.Sheets(1)
activecell = xlSheet.Cells(1,1)
def GetEmptyCell():
global activecell
activecell = xlSheet.Cells(1,1)
for c in range(1,99,1):
if activecell.Value == None:
print 'Empty cell'
activecell = xlSheet.Cells(c,1)
print '(' + str(c) + ',1)'
return activecell
elif activecell.Value != None:
c += 1
activecell = xlSheet.Cells(c,1)
print 'Full cell, next'
GetEmptyCell()
def WriteToEmpty():
global activecell
global HoursWorked
global GrossIncome
global NetIncome
HoursWorked = raw_input('Input amount of hours worked: ')
GrossIncome = float(HoursWorked) * 9.15
NetIncome = float(GrossIncome) * 0.86233
print 'Money Made: ' + str(GrossIncome) + ' Take Home: ' + str(NetIncome)
activecell.Value = time.strftime('%a') + ' ' + time.strftime('%m') + '/' + time.strftime('%d')
#HELP FROM HERE
WriteToEmpty()``
There are dozens of ways to acheive what you want. If you have contiguous data in column A you could use something like xl.range("A1").end(xldown).offset(1,0).address to get the address of the first cell in the next empty row. Or you could use xl.range("A1").currentregion and offset from there.
Personally i'd probably just put the current region into an array and work from there, then dump the array back to the sheet, but thats always my preference, most people seem to prefer to work on the sheet.

Categories