Set timeout for connection to service - python

I have a service and my code tries to connect to it with API:
import my_srvice_api
It haven't any mechanism for timeout and my code stays waiting if the service is not running, I want to try and after timeout raise the exception, how can I do that like this:
timeout = 3
try:
obj = my_service_api.connect()
except TimeoutException as e:
print("service my_service start")

I add this decorator (base on this post) and its works. Thanks to all who attended to this question.
import threading
import sys
class TimeoutError(Exception): pass
def timelimit(timeout):
def internal(function):
def internal2(*args, **kw):
class Calculator(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
try:
function(*args, **kw)
except:
pass
c = Calculator()
c.start()
c.join(timeout)
if c.isAlive():
raise TimeoutError
return internal2
return internal
Then I add this decorator to my function:
#timelimit(2)
def time_out_api():
obj = my_service_api.connect()
try:
time_out_api()
except TimeoutError as e:
print("service my_service start")
exit(0)

Related

How to have a decorator access variables from the decorated function?

I'm using a generic Python timeout decorater. I want the decorater to access variables from the function it is decorating. In this example, I want message to pass from the prepare function into the timeout function. I don't want to use a global variable as that sounds like bad practice.
def timeout(seconds):
def decorator(func):
def _handle_timeout(signum, frame):
# Do something with variable message
print("Sending the message didn't work!")
print(message)
def wrapper(*args, **kwargs):
signal.signal(signal.SIGALRM, _handle_timeout)
signal.alarm(seconds)
try:
result = func(*args, **kwargs)
finally:
signal.alarm(0)
return result
return wraps(func)(wrapper)
return decorator
#timeout(5)
def prepare(message):
"""Deploy app using Heroku to the MTurk Sandbox."""
print("Preparing to send message!")
send(message)
Push the handler into the wrapper so that it has access to that variable.
from functools import wraps
import signal
import time
def timeout(seconds):
def decorator(func):
def wrapper(message, *args, **kwargs):
def _handle_timeout(signum, frame):
# Do something with variable message
print("Sending the message didn't work!")
print(message)
signal.signal(signal.SIGALRM, _handle_timeout)
signal.alarm(seconds)
try:
result = func(message, *args, **kwargs)
finally:
signal.alarm(0)
return result
return wraps(func)(wrapper)
return decorator
#timeout(1)
def prepare(message):
# Uncomment to force error
# time.sleep(3)
"""Deploy app using Heroku to the MTurk Sandbox."""
print("Preparing to send message!")
print(message)
if __name__ == "__main__":
prepare("hi")

sqlalchemy engine.connect() stalled

I use sqlachemy to connect to a remote database but I do not know the type (can be PostgreSQL, MariaDB, etc.). I try them in a loop and I keep the first working driver:
for driver in drivers:
try:
uri = get_uri_from_driver(driver)
engine = create_engine(uri, echo=False)
print('Try connection')
con = engine.engine.connect()
# Try to get some lines
return engine
except Exception:
continue
return None
In some case the con = engine.engine.connect() does not end and it happens when you try the MySQL driver to connect to something which is not MySQL (Oracle).
Questions:
How can I set a timeout to this?
If I cannot, is there any other way to achieve this ? (I will for example base the test order with the default port but I would like to be able to kill the connect() after some seconds.
EDIT:
This code is in a Django so I cannot use signal/alarm because of multi-threading.
This can be done with a generic timeout solution like in:
What should I do if socket.setdefaulttimeout() is not working?
import signal
class Timeout():
"""Timeout class using ALARM signal"""
class TimeoutException(Exception): pass
def __init__(self, sec):
self.sec = sec
def __enter__(self):
signal.signal(signal.SIGALRM, self.raise_timeout)
signal.alarm(self.sec)
def __exit__(self, *args):
signal.alarm(0) # disable alarm
def raise_timeout(self, *args):
raise Timeout.TimeoutException()
# In your example
try:
uri = get_uri_from_driver(driver)
engine = create_engine(uri, echo=False)
print('Try connection')
with Timeout(10):
con = engine.engine.connect()
# Try to get some lines
return engine
except Exception:
continue

Python Tornado web service for long running process

I want to write a web service which processes the request on the background. The service puts the request into a queue and responds the client immediately.
My problem in the code below is that while loop in BackgroundThread().run() function doesn't work.
While loop in BackgroundThread.run() method doesn't act like infinite.It only go into while loop once.
Thank you.
Code:
class BackgroundThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
global queue
while True:
item = queue.get()
if item is not None:
#long running process
time.sleep(random.randint(10, 100) / 1000.0)
print "task", item, "finished"
queue = Queue.Queue()
class MyHandler(tornado.web.RequestHandler):
#gen.coroutine
def get(self):
global queue
self.write('OK')
self.finish()
filePath = self.get_arguments("filePath")
queue.put(filePath)
print queue.qsize()
if __name__=='__main__':
try:
BackgroundThread().start()
BackgroundThread().start()
app = tornado.web.Application([(r'/', MyHandler)])
print("server opened on port : 8000")
server = tornado.httpserver.HTTPServer(app)
server.bind(8000)
server.start(4) # Specify number of subprocesses
tornado.ioloop.IOLoop.current().start()
except KeyboardInterrupt:
print '^C received, shutting down the web server'
sys.exit(1)
I just add try except block because when queue is empty in while loop,it get an exception and doesn't iterate.
I got the answer and here is the code :
class BackgroundThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
global queue
print("qwerqwer0")
while 1==1:
print("qwerqwer1")
print("qwerqwer2")
try:
item = queue.get()
queue.task_done()
except Queue.Empty:
print("empty")
pass
if item is not None:
print("qwerqwerqwer")
#long running process
print "task ", item, " finished"
queue = Queue.Queue()
class MyHandler(tornado.web.RequestHandler):
#gen.coroutine
def get(self):
global queue
self.write('OK')
self.finish()
filePath = self.get_arguments("filePath")
queue.put(filePath)
print queue.qsize()
if __name__=='__main__':
try:
#BackgroundThread().start()
BackgroundThread().start()
app = tornado.web.Application([(r'/', MyHandler)])
print("server opened on port : 8000")
server = tornado.httpserver.HTTPServer(app)
server.bind(8000)
server.start(4) # Specify number of subprocesses
tornado.ioloop.IOLoop.current().start()
except KeyboardInterrupt:
print '^C received, shutting down the web server'
sys.exit(1)

Async http request with python3

Is there any way to make async python3 like node.js do?
I want a minimal example, I've tried the below, but still works with sync mode.
import urllib.request
class MyHandler(urllib.request.HTTPHandler):
#staticmethod
def http_response(request, response):
print(response.code)
return response
opener = urllib.request.build_opener(MyHandler())
try:
opener.open('http://www.google.com/')
print('exit')
except Exception as e:
print(e)
If the async mode works, the print('exit') should display first.
Can anyone help?
Using threading (based on your own code):
import urllib.request
import threading
class MyHandler(urllib.request.HTTPHandler):
#staticmethod
def http_response(request, response):
print(response.code)
return response
opener = urllib.request.build_opener(MyHandler())
try:
thread = threading.Thread(target=opener.open, args=('http://www.google.com',))
thread.start() #begin thread execution
print('exit')
# other program actions
thread.join() #ensure thread in finished before program terminates
except Exception as e:
print(e)

How come the gevent timeout exception is never caught by my except clause?

The code never reaches the print 'never reach1' or print 'never reach2' line when I try to telnet into the server.
import sys, signal
from gevent.server import StreamServer
from gevent.pool import Pool
from gevent import monkey
import gevent
from gevent import Timeout
import random
class SocketPool(object):
def __init__(self):
self.pool = Pool(1000)
def listen(self, socket):
while True:
line = socket.recv(1024)
print line
def add_handler(self, socket, address):
if self.pool.full():
raise Exception("At maximum pool size")
else:
self.pool.spawn(self.listen, socket)
gevent.spawn(self.wait).join()
def wait(self):
try:
timeout = Timeout(1)
timeout.start()
except Timeout:
print 'never reach1'
except:
print 'never reach2'
def shutdown(self): self.pool.kill()
def signal_handler(signal, frame): sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
monkey.patch_all()
sockPool = SocketPool()
server = StreamServer(('127.0.0.1', 5000), sockPool.add_handler)
server.serve_forever()
As you can see from the documentation:
timeout = Timeout(seconds, exception)
timeout.start()
try:
... # exception will be raised here, after *seconds* passed since start() call
finally:
timeout.cancel()
So your try block is completely executed and hence cannot catch the exception.
You should put something like a while loop or a computation that requires at least 1 second to see the exception.
If you want to make a method that simply "sleeps" without using CPU I'd recommend using a simple time.sleep instead of using a Timeout.

Categories

Resources