2010-09-28 6 views
3

J'ai cherché sur ceci mais ne peux pas sembler trouver une réponse exacte (la plupart entrent dans des choses plus compliquées comme le multithreading, etc.), je veux juste faire quelque chose comme une instruction d'essai, excepté si le processus doesn ' t terminer dans X nombre de secondes, il va lancer une exception.Python, Timeout d'essai, sauf relevé après X nombre de secondes?

EDIT: La raison en est que j'utilise un logiciel de test de site Web (sélénium) avec une configuration qui provoque parfois son blocage. Il ne lance pas d'erreur, ne temporise pas et ne fait rien, donc je n'ai aucun moyen de l'attraper. Je me demande quelle est la meilleure façon de déterminer si cela s'est produit afin que je puisse passer à autre chose dans ma demande, alors je me demandais si je pouvais faire quelque chose comme «si cela n'a pas fini de X secondes ... passer à autre chose». .

+0

Lorsque vous dites que vous » re "utiliser un logiciel de test de site Web" - voulez-vous dire que vous l'appelez avec une sorte de "système" ou de tuyau, comme un processus enfant, ou quoi? (désolé si cela est évident pour quelqu'un de familier avec le sélénium, ce que je ne suis pas) –

+0

Eh bien, il a sa propre API construite pour Python donc il importe juste quelques classes de Python Selenium et l'appelle à partir de là, son (sélénium) pas un python application bien que son écrit en javascript – Rick

+0

Merci pour les réponses, cela m'a aidé à pointer dans la bonne direction, ce qui je pense est d'utiliser des processus et de le tuer en fonction de certaines conditions (si elle ne met pas à jour une DB avec une valeur indiquant qu'il a «fini» dans un certain laps de temps) – Rick

Répondre

1

La réponse (et la question) n'est pas spécifique à l'instruction try/except. Si vous voulez avoir une boucle infinie qui n'est pas infinie (mais qui s'arrête après un certain temps), elle ne devrait probablement pas être infinie. Par exemple, changer à utiliser:

while time <= some_value: 

Ou ajouter un contrôle supplémentaire au corps de la boucle, ce qui en fait casser quand vous le voulez arrêter:

while True: 
    ... 
    if time > some_value: 
     break 

Si cela est impossible (par exemple, parce que vous ne contrôlez pas la boucle du tout), les choses deviennent beaucoup plus difficiles. Sur de nombreux systèmes, vous pouvez utiliser signal.alarm pour recevoir un signal après un certain temps, puis disposer d'un gestionnaire de signal pour signal.SIGALRM qui déclenche votre exception TimeoutError. Cela peut ou peut ne pas fonctionner selon ce que fait réellement la boucle infinie; si elle bloque les signaux, ou attrape et ignore les exceptions, ou de toute autre manière interfère avec le gestionnaire de signal, cela ne fonctionnera pas. Une autre possibilité serait de ne pas faire la boucle dans le processus actuel, mais dans un autre; vous pouvez alors terminer le processus séparé à votre guise. Il ne sera pas facile de faire quoi que ce soit mais de le terminer, alors le nettoyage ou la récupération d'un travail partiel est très difficile. (Fils ne vont pas travailler du tout, parce qu'il n'y a aucun moyen d'interrompre le thread séparé faisant la boucle infinie.)

+0

Je n'aurais pas dû utiliser un exemple comme ça, désolé pour la confusion ... ce n'est pas vraiment une boucle (je pensais juste que cela illustrerait ce que j'essayais de faire avec un Try, Excepté) , J'ai ajouté le 'EDIT:' à la poste pour expliquer ce que je fais, c'est un processus externe qui se bloque parfois donc il n'est pas capable de donner des commentaires pour que je puisse le dépasser – Rick

+0

Votre message a été certainement utile, il m'a penser à un moyen de le faire en utilisant une solution memcache/db où je stocke une valeur pour chaque boucle et revenez sur ce que je sais si c'est fini ou non, sinon je viens de tuer ce "mini-processus" – Rick

+0

Utilisation de signaux comme un mécanisme générique de timeout en Python est dangereux. Voir ma réponse à http://stackoverflow.com/questions/366682 (d'ailleurs, un des nombreux exemples de questions SO marquant les mauvaises réponses comme solutions). –

2

Vous ne pouvez pas le faire sans une sorte de multithreading ou de multitraitement, même si cela est caché sous certaines couches d'abstraction, sauf si ce "processus" que vous exécutez est spécifiquement conçu pour l'asynchronicité et le rappel à une fonction connue de temps à autre.

Si vous décrivez ce qu'est réellement ce processus, il sera plus facile de fournir de vraies solutions. Je ne pense pas que vous appréciez la puissance de Python en ce qui concerne les implémentations qui sont succinctes tout en étant complètes. Cela peut prendre quelques lignes de code à implémenter, même si vous utilisez le multithreading/multitraitement.

+0

merci pour l'info ... J'ai mis à jour l'OP avec des informations sur ce que je fais, ce n'est pas que je ne veux pas utiliser multithreading, juste mon cas est un peu inhabituel je pense (peut-être/je l'espère pas? impossible de trouver une solution – Rick

0

Une solution générique si vous utilisez UNIX:

import time as time 
import signal 

#Close session 
def handler(signum, frame): 
    print 1 
    raise Exception('Action took too much time') 


signal.signal(signal.SIGALRM, handler) 
signal.alarm(3) #Set the parameter to the amount of seconds you want to wait 

try: 
    #RUN CODE HERE 

    for i in range(0,5): 
     time.sleep(1) 
except: 
    print 2 

signal.alarm(10) #Resets the alarm to 10 new seconds 
signal.alarm(0) #Disables the alarm 
Questions connexes