我正在仔细阅读此处发布的问题:
What should I do if socket.setdefaulttimeout() is not working?
尝试在mechanize.Browser
对象花费太长时间时提出解决方案来杀死请求,并且我一直在尝试使用tomasz编辑中的第一个解决方案(为了清晰起见,这里重新发布):
import signal, time
def request(arg):
"""Your http request"""
time.sleep(2)
return arg
class Timeout():
"""Timeout class using ALARM signal"""
class Timeout(Exception): pass
def __init__(self, sec):
self.sec = sec
def __enter__(self):
signal.signal(signal.SIGALRM, self.raise_timeout)
signal.alarm(self.sec)
def __exit__(self, *args):
signal.alarm(0) # disable alarm
def raise_timeout(self, *args):
raise Timeout.Timeout()
# Run block of code with timeouts
try:
with Timeout(3):
print request("Request 1")
with Timeout(1):
print request("Request 2")
except Timeout.Timeout:
print "Timeout"
# Prints "Request 1" and "Timeout"
当我使用python timeout.py
从我的终端运行此版本(版本为Python 2.7.2+
而我在Ubuntu 11.10 Oneiric Ocelot上)时,没有抛出任何异常 - 而只是打印
Request 1
Request 2
有人可以解释一下如何解决这个问题吗?有关signal.alarm
和signal.signal
次调用的内容的解释也很棒。
非常感谢你的时间!
编辑:
运行strace -f python timeout.py
会产生:
alarm(3) = 0
select(0, NULL, NULL, NULL, {2, 0}) = 0 (Timeout)
fstat64(1, {st_mode=S_IFREG|0664, st_size=0, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb740c000
alarm(0) = 1
rt_sigaction(SIGALRM, {0x812f450, [], 0}, {0x812f450, [], 0}, 8) = 0
alarm(1) = 0
select(0, NULL, NULL, NULL, {2, 0}) = 0 (Timeout)
alarm(0) = 0
rt_sigaction(SIGINT, {SIG_DFL, [], 0}, {0x812f450, [], 0}, 8) = 0
rt_sigaction(SIGALRM, {SIG_DFL, [], 0}, {0x812f450, [], 0}, 8) = 0
write(1, "Request 1\nRequest 2\n", 20) = 20
exit_group(0) = ?
答案 0 :(得分:1)
如果你想知道这里发生了什么,请尝试:
$ strace -f python timeout.py
对我来说(使用python 2.6运行Debian 6)这是有效的。 strace输出的重要部分:
alarm(3) = 0
select(0, NULL, NULL, NULL, {2, 0}) = 0 (Timeout)
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 15), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = x7f0fbbe06000
write(1, "Request 1\n", 10Request 1) = 10
alarm(0) = 1
rt_sigaction(SIGALRM, {0x4d0a90, [], SA_RESTORER, 0x7f0fbb9deff0}, {0x4d0a90, [], SA_RESTORER, 0x7f0fbb9deff0}, 8) = 0
alarm(1) = 0
select(0, NULL, NULL, NULL, {2, 0}) = ? ERESTARTNOHAND (To be restarted)
--- SIGALRM (Alarm clock) @ 0 (0) ---
rt_sigreturn(0xffffffff) = -1 EINTR (Interrupted system call)
alarm(0) = 0
write(1, "Timeout\n", 8Timeout
) = 8
报警(3)被调用;请求1通过;调用alarm(1),给出超时。