How to loop a function in if else conditions - python

Im trying to loop a function in itself in a special condition but as it re runs the function refreshes the variable "j" also. So i want to use that functions repeadetly to check connection and refresh the page so if i put variables to the out of the functions it will run once and makes it top value so the looping second time will fail. How to fix that?
def checkConnection():
onPage = pyautogui.locateCenterOnScreen('onpage.png', grayscale = True, confidence = 0.8)
noConnectionError = pyautogui.locateCenterOnScreen('noconnection.png', grayscale = True, confidence = 0.8)
sleep(2)
if onInstagram != None:
print("[INFO] : NETWORK STATUS : SUCCESS")
elif noConnectionError != None:
print("[WARNING] : NO CONNECTION !!!")
print("[INFO] TYRING TO RECONNECT...")
sleep(1)
j = 0
while j < 3:
print("[INFIO] REFRESHING PAGE... TRIAL : "+ str(j+1))
refresh()
sleep(3)
checkConnection()
print("[WARNING] : TRY AGAIN FAILED")
sleep(1)
print("[WARNING] : *****QUIT*****")
sleep(5)
quit()

Related

Why is my nested while loop not working? if and second while loop is expected

the program should search for a image in the first loop and add it to a list, in the secon loop should he search till he find a image that isnt already in the list. PyCharm give me the errors that while search = True: and if pic == used is expected.
used = []
search = True
#First Loop
while True:
pic = driver.find_element(By.CSS_SELECTOR,value=".image-post img")
time.sleep(2)
pic_url = pic.get_attribute("src")
pic_title = pic.get_attribute("alt")
used.append(pic)
time.sleep(200)
#Second loop
while search = True:
pic = driver.find_element(By.CSS_SELECTOR, value=".image-post img")
if pic == used
search = True
else:
search = False
used.append(pic)
...
Try this
used = []
#First Loop
while True:
search = True #moved search = True here so that the nested loop will run each iteration of the main loop as it will be set back to True
pic = driver.find_element(By.CSS_SELECTOR,value=".image-post img")
time.sleep(2)
pic_url = pic.get_attribute("src") #you’re not doing anything with this from the looks of it
pic_title = pic.get_attribute("alt") #same with this
used.append(pic)
time.sleep(200)
#Second loop
while search:
pic = driver.find_element(By.CSS_SELECTOR, value=".image-post img")
if pic != used:#may want to change “used” to “used[-1]” here as used is a list while it appears pic is not, so the -1 will get the last value in used
search = False
used.append(pic)
You could also replace search with True and change the “search = False” with “break”
I think that you used a bad operator type. By that, I mean that you should probably use == and not =.
Check it and inform me.

Possible memory leak in Python?

I'm experiencing an issue when calling a function inside a while loop.
The purpose of the while loop is to perform an action ,but it can only perform this action if a certain threshold appeared. This threshold is a result from another function.
When running this for the first time ,everything works ok. No threshold -no run.
The problem is ,that this threshold is affected by other parameters ,and when it changes ,it usually blocks the main program from running.
But ,at certain times, which I cannot pinpoint precisely when ,there's a "slip" and the threshold does not prevent the main program from running.
My question is ,could there be a memory leakage of some sort?
Code is below ,thanks.
def pre_run_check():
if check_outside() != 1:
return (0)
else:
return(1)
if __name__== '__main__':
while True:
time.sleep(0.5)
allow_action = None
while allow_action == None:
print ("cannot run")
try:
allow_action = pre_run_check()
except:
allow_action = 0
else:
if allow_action == 1:
print ("running")
#take action of some sort##
allow_action = None
def pre_run_check():
if check_outside() != 1:
return False
else:
return True
while True:
time.sleep(0.5)
allow_action = pre_run_check()
while not allow_action:
print ("cannot run")
try:
allow_action = pre_run_check()
if allow_action :
print ("running")
#take action of some sort##
allow_action = False
#Actualy need wait end of subprocess, Otherwise got some corrupted data/handle
break
except:
allow_action = False
time.sleep(.5)
This point is how to generate an sequential Process
Hope its helps.

selenium click() method doesn't work after perfectly working a couple of hours before

I'm using selenium to like automatically some pictures. So the script searches for a word, clicks on the first picture, locates the like button then clicks on it.
The click button works to click on the picture but not to like it... I didn't change the identifier, so the class name is perfectly fine. I don't where the problem could come.
Here's my code :
'''
class Interact(Browser):
#click on the firt picture in the page
def firstpic_click(self):
time.sleep(2)
first = self.browser.find_element_by_class_name("kIKUG")
first.click()
#likes curent picture
def like_pic(self):
time.sleep(2)
like = self.browser.find_element_by_class_name("fr66n")
soup = bs(like.get_attribute('innerHTML'),'html.parser')
if (soup.find('svg')['aria-label'] == 'Like'):
like.click()
time.sleep(2)
#returns and clicks on next picture if any
def next_picture(self):
time.sleep(2)
try:
# nex = browser.find_element_by_xpath('//svg[#aria-label="Next"]')
next = self.browser.find_elements_by_class_name("wpO6b ")
soups = [bs(nextt.get_attribute('innerHTML'),'html.parser') for nextt in next]
for i in range(len(soups)):
#print(soups[i])
if (soups[i].find('svg')['aria-label'] == 'Next'):
next[i].click()
return next[i]
#nex = self.browser.find_element_by_xpath('//button[#class="wpO6b "]')
#time.sleep(1)
#return nex
except selenium.common.exceptions.NoSuchElementException:
return 0
#liking all the next pictures if any
def continue_liking(self):
while(True):
next_el = self.next_picture()
if next_el != False:
self.like_pic()
time.sleep(2)
next_el.click()
time.sleep(2)
else:
print("not found")
break
def word_search(self, search=1):
# word = input("what?")
word = "lol"
#search is the method of search
#looking for word in search box
if search == 0:
search_box = self.browser.find_element_by_xpath("//input[#aria-label='Search Input']")
search_box.send_keys("#"+word)
time.sleep(2)
#search_box.send_keys(Keys.RETURN)
#search_box.send_keys(Keys.RETURN)
search_box.submit()
time.sleep(5)
#type the website directly
if search == 1:
self.browser.get("https://www.instagram.com/explore/tags/" + word)
def liking_pictures(browser0):
browser0.implicitly_wait(5)
browser = Interact(browser0)
browser.word_search()
browser.firstpic_click()
browser.like_pic()
browser.next_picture()
browser.continue_liking()
time.sleep(10)
if __name__ == '__main__':
with browse() as browser0:
#unsubscribing(browser0)
liking_pictures(browser0)
'''
Thank you

how to make locateCenterOnScreen more accurate -PYTHON-, -WINDOWS-

Hello my goal is to be able to make my bot click the thing of my choosing on any screen size because I think that is the main issue. Ive tried to decrease the confidence level but it just ends up clicking something else with the same general color. ive tested it with an EXACT image and it clicks the correct spot so its not like the coordinates are off or anything its just the image recognition.
These are the images to go by
(X1, NextLesson, Arrow)
from pyautogui import *
import pyautogui
import time
import keyboard
import random
def NextLesson():
keepGoing = True
while keepGoing == True:
counter = 0
nl_coordinates = pyautogui.locateOnScreen('images/nextLesson.png', confidence=0.4)
print(nl_coordinates) # This will print out where it is
if nl_coordinates:
print(f"I can see it at {nl_coordinates}")
pyautogui.click(nl_coordinates)
keepGoing = False
else:
print("I cannot see it.")
def Arrow():
keepGoing = True
while keepGoing == True:
counter = 0
arrow_coordinates = pyautogui.locateOnScreen('images/arrow.png', confidence=0.4)
print(arrow_coordinates) # This will print out where it is
if arrow_coordinates:
print(f"I can see it at {arrow_coordinates}")
pyautogui.click(arrow_coordinates)
keepGoing = False
else:
print("I cannot see it.")
def X1():
keepGoing = True
while keepGoing == True:
counter = 0
x1_coordinates = pyautogui.locateOnScreen('images/x1.png', confidence=0.4)
print(x1_coordinates) # This will print out where it is
if x1_coordinates:
print(f"I can see it at {x1_coordinates}")
pyautogui.click(x1_coordinates)
keepGoing = False
else:
print("I cannot see it.")
while True:
counter = 0
counter2 = 0
true = True
time.sleep(2)
X1()#
time.sleep(8)
NextLesson()#
time.sleep(10)
Arrow()#
print("calibration complete ")
time.sleep(5)
cords = pyautogui.position()
while counter != 1800:
time.sleep(60)
pyautogui.click(cords) #clicking where ouse is at
print("clicked")
counter += 60
print(counter)
if counter == 1800:
time.sleep(5) #stops code for 5 secs
X1() #clicks mouse to x button
print("clicked x")
time.sleep(5) #stops code for 5 secs
NextLesson() #clicks mouse to the assignment button
print("clicked assignemnt")
time.sleep(15) #stops code for 2 secs
Arrow() #clicks mouse to the second assignment button
print("clicked 2nd assignment button ")
time.sleep(5) #waits 5secs to put cursor at position
cords = pyautogui.position() #grabs position
print("grabbed position")
We can use opencv-python to perform multiscale template matching. The idea is to scale the template image and attempt to locate the resized template in the screenshot. The code below (adapted from here) loops over 50 scaling parameters in the range [0.25,2] and selects the one the that provides the best match. You might want to decrease the range or number of scaling parameters for efficiency. It is also better to save the correct scaling parameter and reuse it for multiple images.
import cv2
import pyscreeze
import numpy as np
import imutils
import pyautogui
def template_match_with_scaling(image,gs=True,confidence=0.8):
"""
Locate an image and return a pyscreeze box surrounding it.
Template matching is done by default in grayscale (gs=True)
Detect image if normalized correlation coefficient is > confidence (0.8 is default)
"""
templateim = pyscreeze._load_cv2(image,grayscale=gs) # template image
(tH, tW) = templateim.shape[:2]
screenim_color = pyautogui.screenshot() # screenshot of image
screenim_color = cv2.cvtColor(np.array(screenim_color),cv2.COLOR_RGB2BGR)
if gs is True:
screenim = cv2.cvtColor(np.array(screenim_color),cv2.COLOR_BGR2GRAY)
else:
screenim = screenim_color
#try different scaling parameters and see which one matches best
found = None #bookeeping variable for the maximum correlation coefficient, position and scale
scalingrange = np.linspace(0.25,2,num=50)
for scale in scalingrange:
resizedtemplate = imutils.resize(templateim, width = int(templateim.shape[1]*scale) ) # resizing with imutils maintains the aspect ratio
r = float(resizedtemplate.shape[1])/templateim.shape[1] # recompute scaling factor
result = cv2.matchTemplate(screenim, resizedtemplate, cv2.TM_CCOEFF_NORMED) # template matching using the correlation coefficient
(_, maxVal, _, maxLoc) = cv2.minMaxLoc(result) #returns a 4-tuple which includes the minimum correlation value, the maximum correlation value, the (x, y)-coordinate of the minimum value, and the (x, y)-coordinate of the maximum value
if found is None or maxVal > found[0]:
found = (maxVal, maxLoc, r)
(maxVal, maxLoc, r) = found
if maxVal > confidence:
box = pyscreeze.Box(int(maxLoc[0]), int(maxLoc[1]), int(tW*r), int(tH*r) )
return box
else:
return None
def locate_center_with_scaling(image,gs=True):
loc = template_match_with_scaling(image,gs=gs)
if loc:
return pyautogui.center(loc)
else:
raise Exception("Image not found")
#sample usage
coords = locate_center_with_scaling('images/arrow.png')
The answer I found is taking a more accurate photo of what I need like trying to remove the background as much greyscale=ture and adding more confidence

Raspberry Pi Python loop stop to work

i manipulate a sensor : HC SR04 to capture a distance.
I'm a newbie in Python and RPI. My code work, I capture distance during a time but one moment the script stop...
My code :
GPIO.setmode(GPIO.BCM)
GPIO_TRIGGER = 23
GPIO_ECHO = 24
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)
def main():
global state
print("ultrasonic")
while True:
print "1s second refresh.."
time.sleep(1)
i = 0
datas = []
average = 0
while i< 1:
GPIO.output(GPIO_TRIGGER, False)
time.sleep(C.time['count'])
GPIO.output(GPIO_TRIGGER, True)
time.sleep(0.00001)
GPIO.output(GPIO_TRIGGER, False)
while GPIO.input(GPIO_ECHO) == 0:
start = time.time()
while GPIO.input(GPIO_ECHO) == 1:
stop = time.time()
distance = (stop-start) * 17000
print "Distance : %.1f" % distance
average = F.getAverage(datas)
print "Average: %.1f" % average
GPIO.cleanup()
The code stop here
while GPIO.input(GPIO_ECHO) == 0:
start = time.time()
THE SOLUTION : with a sample timeout :
now = time()
while GPIO.input(self.gpio_echo) == 0 and time()-now<waitTime:
pass
I am also mucking about with this sensor. My code executes similar to yours and I need no timeout for it to work.
The one difference I can find is this:
while i< 1:
GPIO.output(GPIO_TRIGGER, False)
time.sleep(C.time['count'])
I don't know how long the sleep time is here, but it might be that that's causing the problem. If it would be similar to mine setting the Trigger to false would be directly after the setup of the in/out pins instead, and then there's a two second wait to eliminate noise. Your wait time might be lower, I can't tell. There should be no need to set the trigger to false again just before you send the pulse and, I don't know, but it might be causing a false start. I would change it to this to work similarly to mine and then remove the setting to false in the while loop.
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)
GPIO.output(GPIO_TRIGGER, False)
print("Waiting for sensor to settle\n")
time.sleep(2)
I'm not sure if this will solve the issue without the need for a timeout, but I don't seem to need one.
I've written a module for making an object of the sensor which then allows for some more readable scripting. I'm also quite new to python and not at all an experienced programmer so fun errors might be there somewhere, but it's here below if you want to use it or just compare code:
#! /usr/bin/python3
# dist.py this is a module for objectifying an ultrasonic distance sensor.
import RPi.GPIO as GPIO
import time
class Distancer(object):
#init takes an input of one GPIO for trigger and one for echo and creates the object,
#it searches for a calibration file in the working directory (name)Const.txt, if none
#is found it will initiate a calibration
def __init__(self, trig, cho, name):
self.trigger = trig
self.echo = cho
self.name = name
self.filename = self.name + 'Const.txt'
GPIO.setup(self.trigger, GPIO.OUT)
GPIO.setup(self.echo, GPIO.IN)
GPIO.output(self.trigger, False)
print("Waiting for sensor to calm down")
time.sleep(2)
try:
with open(self.filename, "r") as inConst:
self.theConst = int(inConst.read())
except (OSError, IOError) as e:
print("Not calibrated, initializing calibration")
self.calibrate()
with open(self.filename, "r") as inConst:
self.theConst = int(inConst.read())
#Returns the echo time
def measureTime(self):
GPIO.output(self.trigger, True)
time.sleep(0.00001)
GPIO.output(self.trigger, False)
while GPIO.input(self.echo) == 0:
pulse_start = time.time()
while GPIO.input(self.echo) == 1:
pulse_end = time.time()
pulse_duration = pulse_end - pulse_start
return pulse_duration
#Returns a distance in cm
def measure(self):
return self.measureTime() * self.theConst
#Makes you set up the sensor at 3 different distances in order to find the
#relation between pulse time and distance, it creates the file (name)Const.txt
#in the working directory and stores the constant there.
def calibrate(self):
ten = []
thirty = []
seventy = []
print("Make distance 10 cm, enter when ready")
input()
for i in range(30):
ten.append(10/self.measureTime())
time.sleep(0.2)
print("Make distance 30 cm, enter when ready")
input()
for i in range(30):
thirty.append(30/self.measureTime())
time.sleep(0.2)
print("Make distance 70 cm, enter when ready")
input()
for i in range(30):
seventy.append(70/self.measureTime())
time.sleep(0.2)
allTime = ten + thirty + seventy
theOne = 0.0
for i in range(90):
theOne = theOne + allTime[i]
theOne = theOne / 90
with open(self.filename, "w") as inConst:
inConst.write(str(round(theOne)))
#Will continually check distance with a given interval until something reaches the
#treshold (cm), takes an argument to set wether it should check for something being
#nearer(near) or farther(far) than the treashold. Returns True when treshold is reached.
def distWarn(self, nearfar, treashold):
if nearfar.lower() == "near":
while True:
if self.measure() < treashold:
return True
break
time.sleep(0.2)
if nearfar.lower() == "far":
while True:
if self.measure() > treashold:
return True
break
time.sleep(0.2)
#Will measure with a second interval and print the distance
def keepGoing(self):
while True:
try:
print(str(round(self.measure())) + ' cm')
time.sleep(1)
except KeyboardInterrupt:
print("Won't keep going")
break
I've run it with the code below to test it and everything seems to work. First time it's run it will prompt you to calibrate the sensor by putting it at different distances from something.
#! /usr/bin/python3
import RPi.GPIO as GPIO
import time
import dist as distancer
GPIO.setmode(GPIO.BOARD)
TRIG = 16
ECHO = 18
dist = distancer.Distancer(TRIG, ECHO, 'dist')
def main():
global dist
print(str(round(dist.measureTime(),5)) + ' s')
print(str(round(dist.measure())) + ' cm')
dist.distWarn('near', 10)
print('Warning, something nearer than 10 cm at ' + time.asctime( time.localtime(time.time()) ))
dist.distWarn('far', 10)
print('Warning, something further than 10 cm at ' + time.asctime( time.localtime(time.time()) ))
dist.keepGoing()
GPIO.cleanup()
print('Fin')
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
GPIO.cleanup()
print("Exiting")
time.sleep(1)
I am pretty sure you want
while GPIO.input(GPIO_ECHO)==GPIO.LOW:
start = time.time()
while GPIO.input(GPIO_ECHO) == GPIO.HIGH:
stop = time.time()
I don't think GPIO.input naturally returns zeros or ones, you can test that though.
Not really, I think that i lost the signal, i'll try a timeout in
while GPIO.input(GPIO_ECHO)==GPIO.LOW:
start = time.time()
I think that my program wait indefinitely a signal but he stay to 0
I know this is an old question. The cause of the problem was described in this question https://raspberrypi.stackexchange.com/questions/41159/...
The solution is to add a timeout, like the OP did, to the while loops similar to this:
# If a reschedule occurs or the object is very close
# the echo may already have been received in which case
# the following will loop continuously.
count=time.time()
while GPIO.input(GPIO_ECHO)==0 and time.time()-count<0.1:
start = time.time()
...
# if an object is not detected some devices do not
# lower the echo line in which case the following will
# loop continuously.
stop = time.time()
count=time.time()
while GPIO.input(GPIO_ECHO)==1 and time.time()-count<0.1:
stop = time.time()

Categories

Resources