Examples ======== Poll under the current time in seconds is divisble by 5 ------------------------------------------------------- (Ignoring milliseconds) :: import polling2, time # Wait until the number of seconds (ignoring milliseconds) is divisible by 5. polling2.poll(target=time.time, check_success=lambda x: int(x) % 5 == 0, step=0.5, timeout=6) 1599737060.4507122 Poll every minute until a url returns 200 status code -------------------------------------------------------------- :: import requests polling2.poll( lambda: requests.get('http://google.com').status_code == 200, step=60, poll_forever=True) Poll but ignore specifc exceptions ---------------------------------- If you are creating a new cloud provider instance (e.g. waiting for an EC2 instance to come online), you can continue to poll despite getting ConnectionErrors :: import requests polling2.poll( lambda: requests.get('your.instance.ip').status_code == 200, step=60, ignore_exceptions=(requests.exceptions.ConnectionError,), poll_forever=True) Poll for a file to exist ------------------------ This call will wait until the file exists, checking every 0.1 seconds and stopping after 3 seconds have elapsed :: file_handle = polling2.poll(lambda: open('/tmp/myfile.txt'), ignore_exceptions=(IOError,), timeout=3, step=0.1) # Polling will return the value of your polling function, so you can now interact with it file_handle.close() Note, poll returns the value of whatever the target last returned. Polling for Selenium WebDriver elements --------------------------------------- :: from selenium import webdriver driver = webdriver.Firefox() driver.get('http://google.com') search_box = polling2.poll(lambda: driver.find_element_by_id('search'), step=0.5, timeout=7) search_box.send_keys('python polling') Using the polling timeout exception ----------------------------------- An exception will be raised by the polling function on timeout (or the maximum number of calls is exceeded). This exception will have a 'values' attribute. This is a queue with all values that did not meet the condition. You can access them in the except block. :: import random try: polling2.poll(lambda: random.choice([0, (), False]), step=0.5, timeout=1) except polling2.TimeoutException, te: while not te.values.empty(): # Print all of the values that did not meet the exception print te.values.get() Use a custom checker to decide whether your target has returned what your waiting for -------------------------------------------------------------------------------------- is_truthy() is the default checker for the parameter check_success. But, it's easy to create a custom checker function, that tests whether the value returned by the target is the expected value. Here the target is going to return None, which the custom checker, created by is_value(None) will return True for. :: polling2.poll(target=lambda: None, step=0.1, max_tries=1, check_success=polling2.is_value(None)) # Or another example, where we can test that False is returned by the target. polling2.poll(target=lambda: False, step=0.1, max_tries=1, check_success=polling2.is_value(False)) Using a custom condition callback function ------------------------------------------ :: import requests def is_correct_response(response): """Check that the response returned 'success'""" return response == 'success' polling2.poll( lambda: requests.put('http://mysite.com/api/user', data={'username': 'Jill'}, check_success=is_correct_response, step=1, timeout=10) Logging the return values from the target function --------------------------------------------------- :: import logging import requests def is_correct_response(response): """Check that the response returned 'success'""" return response == 'success' polling2.poll( lambda: requests.put('http://mysite.com/api/user', data={'username': 'Jill'}, check_success=is_correct_response, step=1, timeout=10, log=logging.DEBUG) This will log the string representation of response object to python's logging module at the debug level. A message like this will be sent to the log for each return value. You can change the level by providing a different value to the log parameter. :: poll() calls check_success() There is also an option to log the exceptions that are caught by ignore_exceptions. Note, the full-exception traceback will not be printed in the logs. Instead, the error and it's message (using %r formatting) will appear. In the following code snippet, the ValueError raised by the function `raises_error()` will be sent to the logger at the 'warning' level. :: import polling2 import logging import mock # basicConfig should sent warning level messages to the stdout. logging.basicConfig() # Create a function that raises a ValueError, then a RuntimeError. raises_error = mock.Mock(side_effect=[ValueError('a message'), RuntimeError]) try: polling2.poll( target=raises_error, step=0.1, max_tries=3, ignore_exceptions=(ValueError), # Only ignore the ValueError. log_error=logging.WARNING # Ignored errors should be passed to the logger at warning level. ) except RuntimeError as _e: print "Un-ignored %r" % _e" Poll a target forever --------------------- If you do not want to set a timeout on the polled target, you can set the poll_forever parameter to true. This will poll the target forever *until* the target returns the value you expect. :: from polling2 import poll # Target function returns False. The default check_success looks for a truthy value to be returned. # This will call the target function forever, with a one second wait between polls. poll(target=lambda: False, step=1, poll_forever=True) Note, that setting the timeout parameter to None or 0 has the equivalent effect as setting the poll_forever parameter to true. E.g.: :: from polling2 import poll # Setting timeout to zero is equivalent to setting poll_forever=True. # This call will also poll the target forever. poll(target=lambda: False, step=1, timeout=0) Wrap a target function in a polling decorator --------------------------------------------- Perhaps you'd like to use the decorator syntax to implement the polling functional. No problem! :: from polling2 import poll_decorator import requests @poll_decorator(step=1, timeout=15) def wait_until_exists(uri): return requests.get(uri).status_code != 404 # Call when you please wait_until_exists(uri='http://www.google.com') Inspiration taken from https://github.com/benjamin-hodgson/poll per request from https://github.com/lucasmelin.