OVH Cloud OVH Cloud

Eviter les boucles infinies

6 réponses
Avatar
Python-Fr
Bonjour,
j'aimerais pouvoir =E9viter les boucles infinies ( for et while ) lors
de l'ex=E9cution d'un code non-s=FBr mais j'ignore comment m'y prendre.
J'ai trouv=E9 dans sys la fonction "setrecursionlimit" qui permet la
r=E9cursivit=E9 infinie des fonctions mais je n'ai rien trouv=E9 pour
while...
En ce qui concerne "for", une instruction comme:
>>>table =3D [1]
>>>for a in table: table.append(1)
serait =E9galement probl=E9matique...

Avez-vous une id=E9e ? Un apper du type "setrecursionlimit" serait
parfait, mais je n'ai rien aper=E7u de tel.

6 réponses

Avatar
Bertrand B
Bonjour,
j'aimerais pouvoir éviter les boucles infinies ( for et while ) lors
de l'exécution d'un code non-sûr mais j'ignore comment m'y prendre.
J'ai trouvé dans sys la fonction "setrecursionlimit" qui permet la
récursivité infinie des fonctions mais je n'ai rien trouvé pour
while...
En ce qui concerne "for", une instruction comme:

table = [1]
for a in table: table.append(1)




serait également problématique...

Avez-vous une idée ? Un apper du type "setrecursionlimit" serait
parfait, mais je n'ai rien aperçu de tel.



par exemple tu peux décrémenter un compteur de boucle qui arrivé à 0
emet une exception




Avatar
Christophe Delord
Bonjour,

On 12 Dec 2005 08:18:28 -0800, Python-Fr wrote:

Bonjour,
j'aimerais pouvoir éviter les boucles infinies ( for et while ) lors
de l'exécution d'un code non-sûr mais j'ignore comment m'y prendre.
J'ai trouvé dans sys la fonction "setrecursionlimit" qui permet la
récursivité infinie des fonctions mais je n'ai rien trouvé pour
while...
En ce qui concerne "for", une instruction comme:
table = [1]
for a in table: table.append(1)
serait également problématique...




Avez-vous une idée ? Un apper du type "setrecursionlimit" serait
parfait, mais je n'ai rien aperçu de tel.



Sans toucher à l'interpréteur je ne vois pas trop comment détecter les
boucles infinies.

Par contre si tu cherches à borner le temps d'exécution, tu peux
utiliser les signaux. Par exemple :


import signal

class Timeout(Exception):
pass

def timed_exec(timeout, cmd, glob=None, loc=None):
def timeout_handler(signum, frame):
raise Timeout
if glob is None: glob = globals()
if loc is None: loc = glob
signal.signal(signal.SIGALRM, timeout_handler)
signal.alarm(timeout)
try:
exec cmd in glob, loc
except:
signal.alarm(0)
raise
else:
signal.alarm(0)

for cmd in ["t=[0]nfor x in t[:]: t.append(x)",
"t=[0]nfor x in t: t.append(x)",
"raise IOError"]:
try:
timed_exec(2, cmd)
except Timeout:
print "Commande trop longue :"
print cmd
except IOError:
print "Commande qui leve une exception :"
print cmd
else:
print "Commande terminee :"
print cmd



La fonction timed_exec demande la génération d'un signal ALRM avant
d'exécuter le code non-sûr. Si le signal est reçu une exception est
levée. Si le code se termine correctement (ou avec une exception) on
annule le signal.

Il y a un exemple similaire dans la doc :
http://docs.python.org/lib/node373.html

Sur un système ne gérant pas les signaux on doit pouvoir s'en sortir
avec les threads.


Christophe.




Avatar
loufoque

j'aimerais pouvoir éviter les boucles infinies ( for et while ) lors
de l'exécution d'un code non-sûr


Impose une limite de temps qu'a le code pour s'executer et de mémoire
que celui-ci peut allouer.

Avatar
Python-Fr
Celà me semble parfait !
Reste à tester... :-)
Avatar
Python-Fr
Malheureusement, en ce qui concerne Windows(XP), le module "signal"
semble incomplet:
dir(signal)
['NSIG', 'SIGABRT', 'SIGBREAK', 'SIGFPE', 'SIGILL', 'SIGINT',



'SIGSEGV', 'SIGTERM', 'SIG_DFL', 'SIG_IGN', '__doc__', '__name__',
'default_int_handler', 'getsignal', 'signal']

=> pas de "signal.alarm" ni de "signal.SIGALRM"

( j'aimerais bien permettre une portabilité maximale mais certains OS
ne semblent pas prévus pour ce qui touche à la sécurité...
espérons que Vista comble un peu le trou...)



Avatar
Christophe Delord
Bonsoir,

On 13 Dec 2005 10:41:31 -0800, Python-Fr wrote:

Malheureusement, en ce qui concerne Windows(XP), le module "signal"
semble incomplet:


On peut faire sensiblement la même chose avec les threads. Par exemple :

import threading

class Timeout(Exception):
pass

def timed_exec(timeout, cmd, glob=None, loc=None):
if glob is None: glob = globals()
if loc is None: loc = glob
exc = None
def run_cmd():
global exc
try:
exec cmd in glob, loc
except Exception, exc:
pass
th = threading.Thread(target=run_cmd)
th.start()
th.join(timeout)
if th.isAlive():
th._Thread__stop()
raise Timeout
if exc is not None:
raise exc


La fonction crée un thread qui execute le code et attend au plus
'timeout' secondes. Si le code tourne toujours, il est arrêté et
l'exception Timeout est levée.


Christophe.