我正在尝试对 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()'
“SELECT SLEEP(10)”正在模拟一个慢速查询,但我确实看到了与实际慢速查询相同的行为。
结果:
START: 1254440686.69
TIMEOUT! 1254440696.69
如您所见,它休眠了 10 秒,然后我得到了超时异常。
问题:
- 为什么直到执行完成后我才收到信号?
- 还有其他可靠的方法来限制查询执行时间吗?
最佳答案
@nosklo's twisted-based solution优雅且可行,但如果您想避免对扭曲的依赖,该任务仍然可行,例如:
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()
关于python MySQLDB查询超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1507091/