#python #timeout #calculation
#python #тайм-аут #вычисление
Вопрос:
В настоящее время я работаю над переводом множества математических функций на python для использования для счетного бота в discord (поскольку наш текущий счетный бот не имеет абсолютно никакой забавной математики!).
Я остановился на осознании того, что у меня нет способа предотвратить выполнение больших вычислений, особенно при предоставлении возможности интерпретировать обозначения Кнута со стрелкой вверх и другие функции гипероперации.
Я попытался использовать функцию тайм-аута (поскольку это казалось самым простым способом, который я мог придумать для решения моей проблемы), но, похоже, я неправильно понял, как работает KeyboardInterupt, и теперь я не думаю, что это поможет мне (или будет хорошим вариантом, даже если я заставлю его работать).
Например:
def knuth(a,n,b):
try:
if b == 0:
return 1
if n == 1:
return a**b
return knuth(a, n-1, knuth(a,n,b-1))
except KeyboardInterrupt:
print("Your number is too big yo!")
exit()
#for example knuth(5,2,5) = 5**5**5**5**5 <- I really don't want to calculate anything that big.
Я предполагаю, что это очень распространенная проблема среди тех, кто занимается математикой на python, но все мои поиски привели к способам реализации тайм-аута, который, похоже, не помогает. Есть ли способ обнаружить, что вот-вот произойдет сверхмассивное вычисление, и остановить его до того, как это произойдет?
Ответ №1:
Это интересный вопрос
Вы можете настроить проверку следующим образом: просто выберите свой допуск
tolerance = 10000000000000
def knuth(a,n,b):
try:
if b == 0:
return 1
if n == 1:
return a**b
if knuth(a, n-1, knuth(a,n,b-1)) > tolerance:
return 'too big'
return knuth(a, n-1, knuth(a,n,b-1))
except KeyboardInterrupt:
print("Your number is too big yo!")
exit()
Теперь в идеале вы хотели бы автоматически определять, какой допуск, прежде чем он станет слишком большим, и все начнет зависать, но на данный момент указание большого числа является простым решением
Комментарии:
1. Единственная проблема, с которой я сталкиваюсь, заключается в том, что допуск будет улавливаться только в том случае, если вычисление не до такой степени, чтобы оно приводило к сбою python, который трудно ограничить в зависимости от количества реализованных стрелок. Иногда первая итерация может дать 100, а вторая имеет длину 10E 100000 цифр.
Ответ №2:
Хорошо, я думаю, что решил свою собственную проблему, но это очень запутанный обходной путь и, вероятно, содержит действительно плохие методы кодирования…
import multiprocessing as mp
from queue import Empty #im on python 3 which apparently means queue is lowercased :)
def knuth(a,n,b):
if b == 0:
return 1
if n == 1:
return a**b
return knuth(a, n-1, knuth(a,n,b-1))
def queuebuff(q,a,n,b): #this and def x() were needed for whatever reason for the
q.put(knuth(a,n,b)) #queue to work, otherwise I would time out... not sure why
#couldnt for the life of me get it to work without it.
def x(q,a,n,b): #Also I was just frustrated, this will get renamed to
return (q,a,n,b) #something more meaningful once I figure out what it is doing
#and why I need it for the queue to work...
def queue(a,n,b):
try:
q=mp.Queue()
p = mp.Process(target=queuebuff, args=x(q,a,n,b)) #I know I didn't put this
p.start() #behind a name gate. Wasn't
Queuedval = q.get(timeout=5) #sure what to do if it was.
while not q.empty(): #this just dumps any other queued items in case something
q.get(timeout=5) #goes wrong... no clue if this is good practice.
p.join()
return Queuedval
except Empty:
print('calculation too large stop it!')
p.kill() #I cant join the process or it will hang so this was my solution.
print('multiprocess closed!')
print('children active: ',mp.active_children()) #check for children and parents
print('parents active: ',mp.parent_process()) #seems like it works fine ?