Установка таймаута для механизации. Браузер - PullRequest
2 голосов
/ 16 марта 2012

Я просматривал вопрос, размещенный здесь:

Что делать, если не работает socket.setdefaulttimeout ()?

, чтобы попытаться найти решение для уничтожения запросов, когда мой mechanize.Browser объект занимает слишком много времени, и я экспериментировал с первым решением в редакторе Томаша (для ясности перепечатано здесь):

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 вызовами, также было бы потрясающим.

Большое спасибо за потраченное время!

EDIT:

Запуск 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)                           = ?

1 Ответ

1 голос
/ 16 марта 2012

Если вы хотите узнать, что здесь происходит, попробуйте:

$ strace -f python timeout.py

Для меня (запуск Debian 6 с python 2.6) это работает.прямой выход важной части:

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 поступает;вызывается сигнализация (1), которая дает время ожидания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...