тайм-аут запроса python MySQLDB

, пока Вы сохраняете свой код к исходному файлу , можно получить исходный код объекта с помощью осмотреть модуля.

пример: откройте тип редактора:

myfunction = lambda x: x==2

сохраняют как lamtest.py

, открытый Python типа оболочки для получения до интерактивного Python вводит следующее:

>>>from lamtest import myfunc
>>>import inspect
>>>inspect.getsource(myfunc)

результат:

'myfunc = lambda x: x==2\n'
9
задан mluebke 1 October 2009 в 23:51
поделиться

5 ответов

Решение @ nosklo на основе twisted элегантно и работоспособно, но если вы хотите избежать зависимости от twisted, задача все равно выполнима, например:

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()
8
ответ дан 4 December 2019 в 19:35
поделиться

Почему я не получаю сигнал до завершения выполнения?

Запрос выполняется с помощью функции C, которая блокирует выполнение виртуальной машины Python до тех пор, пока она не вернется.

Есть ли здесь еще один надежный способ ограничить время выполнения запроса?

Это (IMO) действительно уродливое решение, но оно работает . Вы можете запустить запрос в отдельном процессе (либо через fork () , либо через модуль multiprocessing ). Запустите таймер будильника в своем основном процессе и, когда вы его получите, отправьте SIGINT или SIGKILL дочернему процессу. Если вы используете многопроцессорную обработку , вы можете использовать метод Process.terminate () .

1
ответ дан 4 December 2019 в 19:35
поделиться

Используйте adbapi . Это позволяет вам выполнять вызов базы данных асинхронно.

from twisted.internet import reactor
from twisted.enterprise import adbapi

def bogusQuery():
    return dbpool.runQuery("SELECT SLEEP(10)")

def printResult(l):
    # function that would be called if it didn't time out
    for item in l:
        print item

def handle_timeout():
    # function that will be called when it timeout
    reactor.stop()

dbpool = adbapi.ConnectionPool("MySQLdb", user="me", password="myself", host="localhost", database="async")
bogusQuery().addCallback(printResult)
reactor.callLater(4, handle_timeout)
reactor.run()
1
ответ дан 4 December 2019 в 19:35
поделиться

Почему я не получаю сигнал до завершения выполнения?

Процесс ожидает сетевой ввод-вывод находится в бесперебойном состоянии (вещь UNIX, не имеющая отношения к Python или MySQL). Он получает сигнал после завершения системного вызова (вероятно, как код ошибки EINTR , хотя я не уверен).

Есть ли другой надежный способ ограничить время выполнения запроса?

Я думаю, что это обычно выполняется с помощью внешнего инструмента, такого как mkill , который отслеживает MySQL на предмет длительных запросов и уничтожает их.

не имеет отношения к Python или MySQL). Он получает сигнал после завершения системного вызова (вероятно, как код ошибки EINTR , хотя я не уверен).

Есть ли другой надежный способ ограничить время выполнения запроса?

Я думаю, что это обычно выполняется с помощью внешнего инструмента, такого как mkill , который отслеживает MySQL на предмет длительных запросов и уничтожает их.

не имеет отношения к Python или MySQL). Он получает сигнал после завершения системного вызова (вероятно, как код ошибки EINTR , хотя я не уверен).

Есть ли другой надежный способ ограничить время выполнения запроса?

Я думаю, что это обычно выполняется с помощью внешнего инструмента, такого как mkill , который отслеживает MySQL на предмет длительных запросов и уничтожает их.

-1
ответ дан 4 December 2019 в 19:35
поделиться

Я пробовал использовать signal.SIGALRM, чтобы прервать вызов на выполнение, но это, похоже, не работает. Сигнал отправляется, но не перехватывается до тех пор, пока не завершится вызов выполнения.

Библиотека mysql обрабатывает прерванные системные вызовы внутренне, поэтому вы не увидите побочных эффектов SIGALRM до тех пор, пока не завершится вызов API (не считая уничтожения текущего потока или процесс)

Вы можете попробовать исправить MySQL-Python и использовать параметр MYSQL_OPT_READ_TIMEOUT (добавлен в mysql 5.0.25)

2
ответ дан 4 December 2019 в 19:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: