I run selenium in python to do web testing, and I have noticed that, when I have added a longer wait in python, my selenium session is logged-out after a certain point of time.
Below Line of code I use to wait in the code
time.sleep(420)
I have tried to do some fake click during the wait period, but still, I have seen the security logout. is there any approach I can solve this issue?
I use python 3.5 and firefox web driver for testing.
What if you try to insert also a wait to Selenium.
In Java it looks like: SeleniumUtils.sleepQuietly(420);
There should also be a method for Python how to tell Selenium to wait (sleep) for certain time.
In your case, you have to say Selenium to wait, after you have called "the function" or click the button that needs to long (6 minutes) to execute.
when you use sleep() function you cannot do anything in that time. that is very useful between two lines of code where you need some time for processing like you are downloading file so, wait 5 seconds after 5 seconds add new parameters and download another file something like that.
you can surely do clicks without having sleep() function. between to click use sleep of 5 to 10 seconds like this your session will not expire it will run until you do driver.quit().
Related
I realize this is a relatively simple question but I haven't found the answer yet.
I'm using driver.get() in a for loop that iterates through some urls. To help avoid my IP address getting blocked, I've implemented time.sleep(5) before the driver.get statement in the for loop.
Basically, I just want a wait period to make my scraping seem more natural.
I think time.sleep may be causing page crashes. What is the equivalent of time.sleep in selenium? From what I understand, implicitly_wait just sets the amount of time before throwing an exception, but I'm not sure that's what I want here? I want a specific amount of time for the driver to wait.
time.sleep()
The sleep() function is from the time module which suspends execution of the current thread for a given number of seconds.
Now, WebDriver being a out-of-process library which instructs the browser what to perform and at the same time the web browser being asynchronous in nature, WebDriver can't track the active, real-time state of the HTML DOM. This gives rise to some intermittent issues that arise from usage of Selenium and WebDriver those are subjected to race conditions that occur between the browser and the user’s instructions.
As of now Selenium doesn't have any identical method to time.sleep(), however there are two equavalent methods at your disposal and can be used as per the prevailing condition of your automated tests.
Implicit wait: In this case, WebDriver polls the DOM for a certain duration when trying to find any element. This can be useful when certain elements on the webpage are not available immediately and need some time to load.
def implicitly_wait(self, time_to_wait) -> None:
"""
Sets a sticky timeout to implicitly wait for an element to be found,
or a command to complete. This method only needs to be called one
time per session. To set the timeout for calls to
execute_async_script, see set_script_timeout.
:Args:
- time_to_wait: Amount of time to wait (in seconds)
:Usage:
::
driver.implicitly_wait(30)
"""
self.execute(Command.SET_TIMEOUTS, {
'implicit': int(float(time_to_wait) * 1000)})
Explicit wait: This type of wait allows your code to halt program execution, or freeze the thread, until the condition you pass it resolves. As an example:
presence_of_element_located()
visibility_of_element_located()
element_to_be_clickable()
There is no specific method in Selenium for hardcoded pauses like a time.sleep() general Python method.
As you mentioned there is an implicitly_wait and Expected Conditions explicit WebDriverWait waits but both these are NOT a hardcoded pauses.
Both the implicitly_wait WebDriverWait are used for setting the timeout - how long time to poll for some element presence or condition, so if that condition is fulfilled or the element is presented the program flow will immediately continue to the next code line.
So, if you want to put a pause you have to use some general Python method that will suspend the program / thread run like the time.sleep().
Situation: There is a website which requires me to scrape information from it every x seconds. The site in question has information which requires my input, thus I decided to go with Selenium. The action flow looks like that: User can click in the browser section or interact with the website and the Selenium browser will scrape a specific piece of information every x seconds.
What have I tried?:
driver.wait (for any kind of element or a specific time); this, unfortunately, doesn't work as I don't have a specific element the browser shall wait for.
time.sleep(0.5) in a while True loop; this didn't work as the scraping and processing part (which may run simultaneously) took time as well, this time.sleep(0.5) may be off by a few seconds.
I looked into creating a Google Chrome Plugin which may do actions and send that information to the Python script in charge, though this surpassed the efforts it should, hence I decided against it.
To sum up, how can I scrape information from a Selenium Chrome Driver session every fixed amount of time?
You can simply wait for the difference between when you start and end. You also need to make sure you have a time that is greater than the time it takes your program. Used 5 here so if your program takes 1 second to run than it would wait for 5-1=4 seconds. This does get the difference in floating values so you can switch to int and do some checks for 0-1 second.
import time
while True:
now = time.time()
time.sleep(1)
later = time.time()
difference = (later - now)
print(difference)
driver.implicitly_wait(5-difference)
I am using selenium with Firefox to automate some tasks on Instagram. It basically goes back and forth between user profiles and notifications page and does tasks based on what it finds.
It has one infinite loop that makes sure that the task keeps on going. I have sleep() function every few steps but the memory usage keeps increasing. I have something like this in Python:
while(True):
expected_conditions()
...doTask()
driver.back()
expected_conditions()
...doAnotherTask()
driver.forward()
expected_conditions()
I never close the driver because that will slow down the program by a lot as it has a lot of queries to process. Is there any way to keep the memory usage from increasing overtime without closing or quitting the driver?
EDIT: Added explicit conditions but that did not help either. I am using headless mode of Firefox.
Well, This the serious problem I've been going through for some days. But I have found the solution. You can add some flags to optimize your memory usage.
options = Options()
options.add_argument("start-maximized")
options.add_argument("disable-infobars")
options.add_argument("--disable-extensions")
options.add_argument('--no-sandbox')
options.add_argument('--disable-application-cache')
options.add_argument('--disable-gpu')
options.add_argument("--disable-dev-shm-usage")
These are the flags I added. Before I added the flags RAM usage kept increasing after it crosses 4GB (8GB my machine) my machine stuck. after I added these flags memory usage didn't cross 500MB. And as DebanjanB answers, if you running for loop or while loop tries to put some seconds sleep after each execution it will give some time to kill the unused thread.
To start with Selenium have very little control over the amount of RAM used by Firefox. As you mentioned the Browser Client i.e. Mozilla goes back and forth between user profiles and notifications page on Instagram and does tasks based on what it finds is too broad as a single usecase. So, the first and foremost task would be to break up the infinite loop pertaining to your usecase into smaller Tests.
time.sleep()
Inducing time.sleep() virtually puts a blanket over the underlying issue. However while using Selenium and WebDriver to execute tests through your Automation Framework, using time.sleep() without any specific condition defeats the purpose of automation and should be avoided at any cost. As per the documentation:
time.sleep(secs) suspends the execution of the current thread for the given number of seconds. The argument may be a floating point number to indicate a more precise sleep time. The actual suspension time may be less than that requested because any caught signal will terminate the sleep() following execution of that signal’s catching routine. Also, the suspension time may be longer than requested by an arbitrary amount because of the scheduling of other activity in the system.
You can find a detailed discussion in How to sleep webdriver in python for milliseconds
Analysis
There were previous instances when Firefox consumed about 80% of the RAM.
However as per this discussion some of the users feels that the more memory is used the better because it means you don't have RAM wasted. Firefox uses RAM to make its processes faster since application data is transferred much faster in RAM.
Solution
You can implement either/all of the generic/specific steps as follows:
Upgrade Selenium to current levels Version 3.141.59.
Upgrade GeckoDriver to GeckoDriver v0.24.0 level.
Upgrade Firefox version to Firefox v65.0.2 levels.
Clean your Project Workspace through your IDE and Rebuild your project with required dependencies only.
If your base Web Client version is too old, then uninstall it and install a recent GA and released version of Web Client.
Some extensions allow you to block such unnecessary content, as an example:
uBlock Origin allows you to hide ads on websites.
NoScript allows you to selectively enable and disable all scripts running on websites.
To open the Firefox client with an extension you can download the extension i.e. the XPI file from https://addons.mozilla.org and use the add_extension(extension='webdriver.xpi') method to add the extension in a FirefoxProfile as follows:
from selenium import webdriver
profile = webdriver.FirefoxProfile()
profile.add_extension(extension='extension_name.xpi')
driver = webdriver.Firefox(firefox_profile=profile, executable_path=r'C:\path\to\geckodriver.exe')
If your Tests doesn't requires the CSS you can disable the CSS following the this discussion.
Use Explicit Waits or Implicit Waits.
Use driver.quit() to close all
the browser windows and terminate the WebDriver session because if
you do not use quit() at the end of the program, the WebDriver
session will not be closed properly and the files will not be cleared
off memory. And this may result in memory leak errors.
Creating new firefox profile and use it every time while running test cases in Firefox shall eventually increase the performance of execution as without doing so always new profile would be created and caching information would be done there and if driver.quit does not get called somehow before failure then in this case, every time we end up having new profiles created with some cached information which would be consuming memory.
// ------------ Creating a new firefox profile -------------------
1. If Firefox is open, close Firefox.
2. Press Windows +R on the keyboard. A Run dialog will open.
3. In the Run dialog box, type in firefox.exe -P
Note: You can use -P or -ProfileManager(either one should work).
4. Click OK.
5. Create a new profile and sets its location to the RAM Drive.
// ----------- Associating Firefox profile -------------------
ProfilesIni profile = new ProfilesIni();
FirefoxProfile myprofile = profile.getProfile("automation_profile");
WebDriver driver = new FirefoxDriver(myprofile);
Please share execution performance with community if you plan to implement this way.
There is no fix for that as of now.
I suggest you use driver.close() approach.
I was also struggling with the RAM issue and what i did was i counted the number of loops and when the loop count reached to a certain number( for me it was 200) i called driver.close() and then start the driver back again and also reset the count.
This way i did not need to close the driver every time the loop is executed and has less effect on the performance too.
Try this. Maybe it will help in your case too.
I am using python 2.7 with Selenium webdriver for Firefox and I have a problem I can't solve or find solved on the internet.
My task is to open around 10k web pages (adsl router web interfaces - via ip address) and upload new firmware. I wrote the code but in order to finish it I must learn how to make selenium webdriver not to wait for page load like forever, but to wait for 2 minutes(it is time needed for new firmware to upload) and then proceed to next step.
I thought I let it wait for forever (wait for router to reconnect - much slower but doable by me without help) but the catch is when I click upload button it takes 2 minutes of uploading new firmware, then router reboots to apply changes (takes less then 2 minutes), then tries to connect (around 10 seconds) and even then if it gets some other IP it will never load and my program wait for forever.
So, I want to skip all of that and I want program to proceed to next router after first 2 minutes. Can it be done? I read something about "pageLoadingStrategy" but I couldn't understand how to use it.
Please write me if it is not understandable, because English is not my native language. Below you can see the code sample, after button.submit() it should wait for 2 minutes and proceed and not wait forever:
def firmware_upload():
global ip
br.get("http://"+ip+"/upload.html")
button = br.find_element_by_xpath('//input[#type="file" and #name="filename"]')
button.send_keys("/home/djura/Downloads/KW5815A_update_140417")
button.submit()
print ("Odradjen UPDATE SOFTWARE-a!")
return
see if this works.
try
{
br.manage().timeouts().pageLoadTimeout(2, TimeUnit.MINUTES);
global ip
br.get("http://"+ip+"/upload.html")
button = br.find_element_by_xpath('//input[#type="file" and #name="filename"]')
button.send_keys("/home/djura/Downloads/KW5815A_update_140417")
button.submit()
print ("Odradjen UPDATE SOFTWARE-a!")
return
}
catch(TimeoutException e)
{
print("2min over");
}
The problem is probably because you are using button.submit, which if I'm not mistaken waits for the return of the action. So instead you should find the actual submit button and click on it using click, e.g.
submit_button = br.find_element_by_id('SUBMIT_BTN_ID')
submit_button.click()
P.S. the fact that in your example code your button variable actually refers to an input element is misleading.
I am working on selenium with python for downloading file from a url.
from selenium import webdriver
profile = webdriver.FirefoxProfile()
profile.set_preference('browser.download.folderList', 2) # custom location
profile.set_preference('browser.download.manager.showWhenStarting', False)
profile.set_preference('browser.download.dir', '/tmp')
profile.set_preference('browser.helperApps.neverAsk.saveToDisk', 'text/csv')
browser = webdriver.Firefox(profile)
try:
browser.get("http://www.drugcite.com/?q=ACTIMMUNE")
browser.find_element
browser.find_element_by_id('exportpt').click()
browser.find_element_by_id('exporthlgt').click()
except:
pass
I want to set timeout for this program. Means, If within 60 seconds if this url is not loaded due to net issue, it should retry after each 60 seconds and after 3 tries, it should go ahead.
How can I achieve such in this code?
Thanks
You could use browser.implicitly_wait(60)
WebDriver.implicitly_wait
There is nothing built in to do this. However, I wouldn't have said it would be too hard.
Just use an explicit wait to find a particular element that should be there when the page loads. Set the timeout to be 60 seconds on this explicit wait.
Wrap this in a loop that executes up to three times. To avoid it running three times unnecessarily, put in a break statement when the explicit wait actually runs without any issue.
That means it'll run up to three times, waiting 60 seconds a time, and once it's successful it'll exit the loop. If it isn't successful after all of that, then it'll crash.
Note: I've not actually tried this but it's just a logical solution!