Bonjour, Je travaille depuis peu sur un algorithme python (j'apprend python en même temps) qui permet d'étudier des fonctions mathématiques (avec l'aide de Sympy notamment). Je cherche à mettre en place un système qui limite la durée d'exécution de certaines fonctions python, par exemple le calcul d'une limite d'une fonction qui serait beaucoup trop long.... Après maintes recherches, j'ai trouvé ce qui suit sur le net et l'ait modifié pour mon cas.... Ca à l'air de fonctionner mais je ne sais pas si le Thread est vraiment arrêté à la fin, dans le cas où le timeout est dépassé et dans le cas ou le calcul dure moins longtemps ?!
Je lis la documentation et je vois qu'en passant un argument à join(timeout=None), on bloque le thread depuis lequel on appel join et on attend que le thread ait terminé, qu'il ait lancé une exception ou que le timeout soit passé. Voir doc
Donc on est sûr d'arriver en ligne 15 seulement si le thread est fini ou si le timeout est passé. Les conditions permettent de vérifier dans quel cas on se trouve.
Oui, l'OP nous indique d'ailleurs que ça fonctionne bien, join est débloqué une fois le timeout écoulé.
Cependant, il est fort probable que le thread continue son exécution, ce qui n'a plus aucune utilité et consomme des ressources.
Effectivement la doc explique que la méthode join() se termine jusqu'à ce que le timeout en option se produise... donc ça devrait effectivement s'arrêter dans tous les cas.
Je vais également essayer la solution de entwanne pour voir ce que ça donne.
J'ai testé de mon côté, et en effet, bien que le join soit débloqué, la console reste ouverte en attendant que le thread soit terminé.
Je peux te proposer une autre solution. Si tu utilises Python 3.4, il y a la nouvelle librairie asyncio qui permet de programmer dans un seul thread.
Voici un code qui montre comment créer une fonction de calcul qui rend la main à chaque itération. Ca permet donc d'attendre un temps donné et d'arrêter la fonction si nécessaire.
!/usr/bin/env python3
-- coding: utf8 --
import asyncio, math
@asyncio.coroutine
def wait_one_step():
"""Coroutine that completes after a BaseEventLoop step."""
future = asyncio.futures.Future()
result = None
handle = future._loop.call_soon(future._set_result_unless_cancelled, result)
try:
return (yield from future)
finally:
handle.cancel()
@asyncio.coroutine
def heavy_computation(future):
"""Dummy function making a lot of computations."""
a = 0
for i in range(1, 1000000):
a += math.sqrt(i) / i
yield from wait_one_step()
future.set_result(a)
</pre>
Tu peux essayer avec différentes valeurs à la ligne 21 pour voir soit la coroutine retourner une valeur, soit le message Time elapsed apparaître.
Ca prend un peu de temps de penser en terme de coroutine, mais ça pourrait être une approche concrète et portable pour toi.
C'est un peu compliqué pour moi qui débute dans le langage python... mais je vais essayer de le tester !
Oui j'utilise python 3.4, je vais tenter ta solution ce soir en l'adaptant à mon algorithme. Si j'ai bien compris, il faut que je remplace la boucle 'for' par ma fonction à tester, et je suppose que le timeout est la valeur 3.0 dans les arguments de 'asyncio.wait_for()' ?
Oui c'est bien ça. Par contre tu dois comprendre que la fonction que tu veux y mettre doit rendre la main assez souvent. Donc s'il n'y a pas de boucles dans ta fonction, ça ne va pas être possible. S'il y a une boucle du type while ou for, il te suffit alors de placer le yield from wait_one_step() dedans pour rendre la main à la boucle principale.
Par contre si ta fonction est une fonction du style Numpy sans une boucle accessible (car écrite en langage C), alors cette méthode ne fonctionnera pas.
Je viens de lire ta réponse et donc ce n'est pas la peine que j'essaie, car la fonction que je souhaite tester est la fonction de calculs de limites 'limit()' de Sympy !!
Tant pis ;(
Merci quand même d'avoir essayer de résoudre mon problème...
from multiprocessing import Pool, TimeoutError
def execTimeOut(func, args, t=30, default=None):
result = pool.apply_async(f, args)
try:
return result.get(timeout=t)
except TimeoutError:
return default
pool = Pool(processes=1)
# execution de la fonction
- Edité par Anonyme 9 février 2015 à 21:08:39
Limiter le temps d'exécution d'une fonction
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
entwanne — @entwanne — Un zeste de Python — La POO en Python — Notions de Python avancées — Les secrets d'un code pythonique
entwanne — @entwanne — Un zeste de Python — La POO en Python — Notions de Python avancées — Les secrets d'un code pythonique