, пока Вы сохраняете свой код к исходному файлу , можно получить исходный код объекта с помощью осмотреть модуля.
пример: откройте тип редактора:
myfunction = lambda x: x==2
сохраняют как lamtest.py
, открытый Python типа оболочки для получения до интерактивного Python вводит следующее:
>>>from lamtest import myfunc
>>>import inspect
>>>inspect.getsource(myfunc)
результат:
'myfunc = lambda x: x==2\n'
Решение @ 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()
Почему я не получаю сигнал до завершения выполнения?
Запрос выполняется с помощью функции C, которая блокирует выполнение виртуальной машины Python до тех пор, пока она не вернется.
Есть ли здесь еще один надежный способ ограничить время выполнения запроса?
Это (IMO) действительно уродливое решение, но оно работает . Вы можете запустить запрос в отдельном процессе (либо через fork ()
, либо через модуль multiprocessing
). Запустите таймер будильника в своем основном процессе и, когда вы его получите, отправьте SIGINT
или SIGKILL
дочернему процессу. Если вы используете многопроцессорную обработку
, вы можете использовать метод Process.terminate ()
.
Используйте 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()
Почему я не получаю сигнал до завершения выполнения?
Процесс ожидает сетевой ввод-вывод находится в бесперебойном состоянии (вещь UNIX, не имеющая отношения к Python или MySQL). Он получает сигнал после завершения системного вызова (вероятно, как код ошибки EINTR
, хотя я не уверен).
Есть ли другой надежный способ ограничить время выполнения запроса?
Я думаю, что это обычно выполняется с помощью внешнего инструмента, такого как mkill
, который отслеживает MySQL на предмет длительных запросов и уничтожает их.
EINTR
, хотя я не уверен).
Есть ли другой надежный способ ограничить время выполнения запроса?
Я думаю, что это обычно выполняется с помощью внешнего инструмента, такого как mkill
, который отслеживает MySQL на предмет длительных запросов и уничтожает их.
EINTR
, хотя я не уверен).
Есть ли другой надежный способ ограничить время выполнения запроса?
Я думаю, что это обычно выполняется с помощью внешнего инструмента, такого как mkill
, который отслеживает MySQL на предмет длительных запросов и уничтожает их.
Я пробовал использовать signal.SIGALRM, чтобы прервать вызов на выполнение, но это, похоже, не работает. Сигнал отправляется, но не перехватывается до тех пор, пока не завершится вызов выполнения.
Библиотека mysql обрабатывает прерванные системные вызовы внутренне, поэтому вы не увидите побочных эффектов SIGALRM до тех пор, пока не завершится вызов API (не считая уничтожения текущего потока или процесс)
Вы можете попробовать исправить MySQL-Python и использовать параметр MYSQL_OPT_READ_TIMEOUT (добавлен в mysql 5.0.25)