mlu*_*bke 9 python mysql timeout
我试图在python MySQLDB中强制执行查询的时间限制.我有一种情况,我无法控制查询,但需要确保它们不会超过设定的时间限制.我已经尝试使用signal.SIGALRM中断执行的调用,但这似乎不起作用.信号被发送,但是在执行完成调用之后才会被捕获.
我写了一个测试用例来证明这种行为:
#!/usr/local/bin/python2.6
import time
import signal
from somewhere import get_dbc
class Timeout(Exception):
""" Time Exceded """
def _alarm_handler(*args):
raise Timeout
dbc = get_dbc()
signal.signal(signal.SIGALRM, _alarm_handler)
signal.alarm(1)
try:
print "START: ", time.time()
dbc.execute("SELECT SLEEP(10)")
except Timeout:
print "TIMEOUT!", time.time()'
Run Code Online (Sandbox Code Playgroud)
"SELECT SLEEP(10)"模拟慢速查询,但我确实看到了与实际慢速查询相同的行为.
结果:
START: 1254440686.69
TIMEOUT! 1254440696.69
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,它已经睡了10秒然后我得到了Timeout Exception.
问题:
@nosklo基于扭曲的解决方案优雅且可行,但如果你想避免对扭曲的依赖,那么任务仍然可行,例如:
import multiprocessing
def query_with_timeout(dbc, timeout, query, *a, **k):
conn1, conn2 = multiprocessing.Pipe(False)
subproc = multiprocessing.Process(target=do_query,
args=(dbc, query, conn2)+a,
kwargs=k)
subproc.start()
subproc.join(timeout)
if conn1.poll():
return conn1.recv()
subproc.terminate()
raise TimeoutError("Query %r ran for >%r" % (query, timeout))
def do_query(dbc, query, conn, *a, **k):
cu = dbc.cursor()
cu.execute(query, *a, **k)
return cu.fetchall()
Run Code Online (Sandbox Code Playgroud)