В моей системе Mac OS X с MacPorts я проверил ваш код со многими версиями Python. Единственная версия, в которой отображается найденная вами ошибка, равна 2,7. Таймаут работает в 2.4, 2.5, 2.6, 3.3 и 3.4.
Теперь, почему это происходит, и что можно сделать по этому поводу?
Я думаю, что это происходит потому, что ваш foobar()
- это замкнутая петля, которая никогда не «возвращает» управление в основной цикл Python. Он работает как можно быстрее, не делая никакой полезной работы, но не позволяя Python обрабатывать сигнал.
Это поможет понять, как обычно обрабатываются сигналы в * nix. Поскольку несколько функций библиотеки являются «безопасными для асинхронного сигнала», мало что можно сделать в обработчике сигналов C напрямую. Python должен вызывать ваш обработчик сигнала, который написан на Python, но он не может сделать это непосредственно в обработчике сигнала, который он регистрирует с использованием C. Так что типичная вещь, которую программы выполняют в своих обработчиках сигналов, - это установить некоторый флаг, чтобы указать, что сигнал был получен, а затем возвращен. В основном цикле, этот флаг проверяется (либо напрямую, либо с помощью «трубы», который может быть записан в обработчик сигнала, и poll()
ed или select()
ed on).
Так что я бы предположить, что основной цикл Python, к счастью выполнения вашей foobar()
функции, и сигнал приходит, он устанавливает некоторое внутреннее состояние, чтобы знать, что необходимо обрабатывать этот сигнал, а затем его ждет на foobar()
до конца, или сбой, по крайней мере, для foobar()
для вызова некоторой прерывистой функции, такой как sleep()
или print()
.
И действительно, если вы добавляете либо сон (за любое количество времени), либо оператор print
в цикл foobar()
, вы получите таймаут, который вы желаете в Python 2.7 (а также в других версиях).
В общем-то, неплохо по-прежнему коротко спать в петлях занятости, чтобы «расслабить» их, тем самым помогая планировать другую работу, которая может потребоваться. Вам также не нужно спать на каждой итерации - только крошечный сон каждые 1000 раз через цикл будет работать нормально в этом случае.
Возможно, ошибка python. Это работает под pypy. Я думаю, вы должны записать это на трекер ошибок. – simonzack
В какой ОС вы работаете? Окна? – Ewan
@Ewan 'SIGALRM' существует только на linux. – simonzack