0

我需要限制函数执行时间,所以我跟着Josh Lee 回答

try:
    with time_limit(10):
        long_function_call()
except TimeoutException, msg:
    print "Timed out!"

其中 long_function_call() 是一个 selenium webdriver 函数,它与页面交互并执行一些操作。

def long_function_call(self, userName, password):
    driver = self.initDriver()
    try: 
         driver.get("https://yyyy.com")
         time.sleep(2)
         if not self.isHttps(driver.current_url):
              isHttps = False             
         driver.find_element_by_id("i015516").clear()
         time.sleep(5)
         if 'https://yyy.com' not in driver.current_url:
             self.raiseFailedToLogin('yyy')                    
    except Exception as e:
        self.raiseException('yyy',e)
    finally:
        driver.close()
        driver.quit()
    return 'yyyy' 

在大多数情况下,当函数执行时间超过信号超时时,发送信号并停止方法,但在某些情况下,方法超过超时并没有停止。似乎 selenium 挂了。(firefox 是打开的,没有做任何事情)。

在这些情况下,我尝试暂停调试器,但暂停并没有告诉我它挂在哪里。如果我关闭 selenium firefox 而不是在此方法上停止调试暂停:

_read_status [httplib.py:366]   
begin [httplib.py:407]  
getresponse [httplib.py:1030]   
do_open [urllib2.py:1180]   
http_open [urllib2.py:1207]
def _read_status(self):
    # Initialize with Simple-Response defaults
    line = self.fp.readline()
    if self.debuglevel > 0:  ################Hang here

知道为什么在某些情况下用硒发出警报信号不起作用吗?(我不认为他们抓住中断)。

4

1 回答 1

0

这是您面临的一个非常有趣的问题。我创建了一个示例,可以演示您在使用with time_limit. 如果您运行下面的代码,您可能会期望在 1 秒后 aTimeoutException将被引发,然后退出 python 并且正在运行的线程以及 xterm 应该都退出。一秒钟后会发生什么,TimeoutException然后您会看到“超时!” 出现在终端中,但线程和 xterm 都将继续执行。这可能是您在使用 selenium 时所面临的场景类型。我不知道 selenium 是如何实现的,但是必须以类似于示例中 xterm 的方式生成 firefox 进程。

简单的方法

import time, os, sys, subprocess, threading

def worker():
    for i in range(30):
        print i
        time.sleep(0.1)

try:
    with time_limit(1):
        threading.Thread(target=worker).start()
        subprocess.check_output('/usr/bin/xterm')
except TimeoutException, msg:
    print "Timed out!"

这个问题的一个潜在解决方案是下面的代码。它会杀死这个python程序的所有孩子,在这种情况下会杀死xterm,然后它会杀死自己。这当然是一种强有力的退出方式,但可以保证一切都在超时时结束。

杀光他们

subprocess.call('pkill -P %s' % os.getpid(), shell=True)
subprocess.call('kill -9 %s' % os.getpid(), shell=True)

考虑到您在下面的评论,另一种方法是让另一个线程在主线程中的操作超过指定超时时执行终止操作。这是具有示例调用的该方法的实现。

在超时时监视和杀死的线程

import time, os
from subprocess import check_output, call
from threading import Thread
from contextlib import contextmanager

def wait_thread(active, duration):
    start = time.time()
    while active[0] and time.time() - start < duration:
        time.sleep(0.1)
    if active[0]:
        call('pkill -P %s' % os.getpid(), shell=True)
        call('kill -9 %s' % os.getpid(), shell=True)

@contextmanager
def wait(duration):
    active = [True]
    Thread(target=wait_thread, args=(active, duration)).start()
    yield
    active[0] = False

with wait(1):
    time.sleep(0.5)
    print 'finished safely before timeout'
with wait(1):
    call('/usr/bin/xterm')
于 2012-11-13T17:04:49.457 回答