Легкая часть вашего вопроса связана с обработкой сигналов.С точки зрения среды выполнения Python, сигнал, который был получен во время выполнения системным вызовом интерпретатором, представляется вашему коду Python как исключение OSError с атрибутом errno
, соответствующим errno.EINTR
Так что этовероятно, работает примерно так, как вы предполагали:
#!/usr/bin/env python
import signal, os, errno, time
def handler(signum, frame):
# print 'Signal handler called with signal', signum
#raise IOError("Couldn't open device!")
print "timed out"
time.sleep(3)
def foo():
# Set the signal handler and a 5-second alarm
signal.signal(signal.SIGALRM, handler)
try:
signal.alarm(3)
# This open() may hang indefinitely
fd = os.open('/dev/ttys0', os.O_RDWR)
except OSError, e:
if e.errno != errno.EINTR:
raise e
signal.alarm(0) # Disable the alarm
foo()
print "hallo"
Примечание. Я удалил импорт time
из определения функции, так как кажется, что это плохая форма, чтобы скрыть импорт таким образом.Мне не совсем понятно, почему вы спите в обработчике сигналов, и на самом деле это кажется довольно плохой идеей.
Ключевой момент, который я пытаюсь сделать, заключается в том, что любой (неигнорируется) сигнал прервет вашу основную строку выполнения кода Python.Ваш обработчик будет вызываться с аргументами, указывающими, какой номер сигнала инициировал выполнение (позволяя использовать одну функцию Python для обработки множества различных сигналов) и объект фрейма (который можно использовать для отладки или инструментария какого-либо рода).
Поскольку основной поток через код прерывается, вам необходимо обернуть этот код в некоторую обработку исключений, чтобы восстановить контроль после того, как такие события произошли.(Между прочим, если вы пишете код на C, у вас возникнет та же проблема; вы должны быть готовы к любым из ваших библиотечных функций с базовыми системными вызовами, чтобы возвращать ошибки и обрабатывать -EINTR в системе errno повторяя цикл, чтобы повторить попытку или перейти к некоторой альтернативе в основной строке (например, перейти к другому файлу или без какого-либо файла / ввода и т. д.).
Как указали другие в своих ответах на ваш вопрос,основание вашего подхода на SIGALARM может быть сопряжено с проблемами переносимости и надежности. Хуже того, некоторые из этих проблем могут быть гоночными условиями, с которыми вы никогда не столкнетесь в своей среде тестирования, и могут возникнуть только в условиях, которые чрезвычайно трудно воспроизвести.Ужасные детали, как правило, возникают в случаях повторного входа --- что произойдет, если сигналы будут отправлены во время выполнения вашего обработчика сигналов?
Я использовал SIGALARM в некоторых сценариях, и это не было проблемой дляя под Linux. Код, над которым я работал, подходил для задание.Это может быть достаточно для ваших нужд.
На ваш основной вопрос трудно ответить, не зная больше о том, как ведет себя этот код Gnuradio, какие объекты вы создаете из него и какие объекты они возвращают.
Взглянув на документы, с которыми вы связались, я вижу, что они, похоже, не предлагают какого-либо аргумента или параметра "тайм-аута", которые можно было бы использовать для непосредственного ограничения блокирующего поведения.В таблице в разделе «Управление потоковыми графами» я вижу, что они конкретно говорят, что .run()
может выполняться бесконечно или до получения SIGINT.Я также отмечаю, что .start()
может запускать потоки в вашем приложении и, похоже, возвращает управление вашей строке кода Python во время их работы.(Кажется, это зависит от природы ваших потоковых графиков, которые я недостаточно понимаю).
Звучит так, как будто вы можете создавать свои потоковые графики, .start()
их, а затем (после некоторой обработки времени).или спать в основной строке кода Python) вызовите метод .lock()
для вашего управляющего объекта (tb?).Я предполагаю, что это переводит представление состояния Python ... объект Python ... в режим покоя, чтобы вы могли запрашивать состояние или, как говорится, перенастраивать свой потоковый граф.Если вы позвоните .run()
, он позвонит .wait()
после того, как позвонит .start()
;и .wait()
, по-видимому, будет работать до тех пор, пока все блоки не "покажут, что они выполнены" или пока вы не вызовете метод .stop()
объекта.
Так что похоже на то, что вы хотите использовать .start()
и ни .run()
ни .wait()
;затем позвоните .stop()
после выполнения любой другой обработки (включая time.sleep()
).
Возможно, что-то простое:
tb = send_seq_2.top_block()
tb.start()
time.sleep(endtime - time.time())
tb.stop()
seq1_sent = True
tb = send_seq_2.top_block()
tb.start()
seq2_sent = True
.. хотя я с подозрением отношусь к своему time.sleep()
там.Возможно, вы хотите сделать что-то еще, когда вы запрашиваете состояние объекта tb
(возможно, влечет за собой сон в течение меньших интервалов, вызывает его метод .lock()
и получает доступ к атрибутам, о которых я ничего не знаю, а затем вызывает его .unlock()
перед повторным сном.