4

У меня есть сценарий сервера, который мне нужно, чтобы иметь возможность отключиться. При тестировании обычных заявлений try..except я понял, что Ctrl-C не работает обычным способом. Обычно я обернуть долго выполняющиеся задачи, как этотПочему мой сценарий python для многопоточности/многопроцессорности не работает правильно?

try: 
    ... 
except KeyboardInterrupt: 
    #close the script cleanly here 

так может быть задача отключения чисто на Ctrl-C. Я никогда не сталкивался с какими-либо проблемами с этим раньше, но почему-то, когда я нажимаю Ctrl-C, когда этот конкретный скрипт запускается, сценарий просто выходит, не вылавливая Ctrl-C.

Начальная версия была реализована с использованием Process от multiprocessing. Я переписал сценарий, используя Thread от threading, но такой же вопрос есть. Я использовал threading много раз раньше, но я новичок в библиотеке multiprocessing. В любом случае, я никогда не испытывал этого поведения Ctrl-C.

Обычно я всегда применял часовые и т. Д., Чтобы закрыть Queues и Thread экземпляры упорядоченным образом, но этот скрипт просто выходит без ответа.

Последний, я попытался перекрывая signal.SIGINT, а как этот

def handler(signal, frame): 
    print 'Ctrl+C' 

signal.signal(signal.SIGINT, handler) 
... 

Здесь Ctrl+C был на самом деле поймали, но обработчик не выполняет, он никогда не печатает ничего.

Помимо аспекта threading/multiprocessing, части сценария содержит C++SWIG объектов. Я не знаю, связано ли это с этим. Я запускаю Python 2.7.2 на OS X Lion.

Итак, несколько вопросов:

  1. Что здесь происходит?
  2. Как я могу отладить это?
  3. Что мне нужно, чтобы узнать, чтобы понять первопричину?

ПОЖАЛУЙСТА, ОБРАТИТЕ ВНИМАНИЕ: внутренности скрипта являются собственностью, поэтому я не могу привести примеры кода. Тем не менее, я очень хочу получить указатели, чтобы сам отлаживал это. Я достаточно опытен, чтобы понять это, если кто-то может указать мне в правильном направлении.

EDIT: я начал комментирование импорта и т.д., чтобы увидеть, что вызвало странное поведение, и я сузил его до ввоза C++ SWIG библиотеки. Любые идеи, почему импорт библиотеки C++ SWIG «ворует» Ctrl-C? Однако я не являюсь автором виноватой библиотеки, и мой опыт SWIG ограничен, поэтому не знаю, с чего начать ...

EDIT 2: Я просто попробовал один и тот же скрипт на машине для Windows и в Windows 7 Ctrl-C пойман как и ожидалось. Я не собираюсь беспокоиться о части OS X, сценарий будет работать в среде Windows в любом случае.

+0

Невозможно сказать, не зная, что вы делаете между 'try:' и 'except ...:'. Код C++ что-то делает с сигналами? Если так, то все может случиться. –

+0

[полный минимальный пример] (http://sscce.org/) может помочь. – jfs

+0

Извините, не может этого сделать. Однако я добавил некоторые выводы. Я все уши для SWIG-мнений и предложений ... – c00kiemonster

ответ

4

Это может быть связано с тем, как Python управляет потоками, сигналами и вызовами C.

Короче - Ctrl-C не может прерывать вызовы C, так как реализация требует, чтобы питон поток будет обрабатывать сигнал, а не только какой-либо поток, но основной поток (часто блокируется, ожидая других потоков).

Фактически, длинные операции могут блокировать все.

Рассмотрим это:

>>> nums = xrange(100000000) 
>>> -1 in nums 
False (after ~ 6.6 seconds) 
>>> 

Теперь попробуйте нажать Ctrl-C

>>> nums = xrange(100000000) 
>>> -1 in nums 
^C^C^C (nothing happens, long pause) 
... 
KeyboardInterrupt 
>>> 

Причина Ctrl-C не работает с резьбовыми программ является то, что основной поток (источник бесперебойного!) часто блокируются при непрерывном потоковом соединении или блокировке (например, любые «wait», «join» или просто пустой пустой «основной» поток, который в фоновом режиме заставляет python «присоединяться» к любому порожденному потоку).

Попробуйте вставить простой

while True: 
    time.sleep(1) 

в основном потоке.

Если у вас есть длительная функция C, выполните обработку сигнала на уровне C (дайте Силе быть с вами!).

Это в значительной степени основано на video Дэвида Безли по этому вопросу.

+0

Этот основной поток Python, на который вы ссылаетесь, контролируется Global Interpreter Lock (GIL), и он много подходит для многопоточных инструкций Python.Из того, что я прочитал, вам лучше использовать многопроцессорную обработку, которая в Python работает достаточно хорошо. Процессы не блокируются GIL. – octopusgrabbus

+0

Возможно, что «многопроцессорная обработка» - это путь к вопросам GIL. Удивительно легко работать, поскольку он отражает библиотеку 'threading'. То есть, пока вы не столкнетесь с такими проблемами, как я. Тогда никто не услышит, как вы кричите. – c00kiemonster

1

Он выходит из-за того, что что-то еще, скорее всего, поймает KeyboardInterupt, а затем поднимает другое исключение или просто возвращает None. Вы должны получить трассировку для отладки. Вам нужно захватить вывод stderr или запустить ваш скрипт с параметром командной строки -i, чтобы вы могли видеть трассировку. Кроме того, добавьте еще один блок, чтобы поймать все остальные исключения.

Если вы подозреваете, что вызов функции C++ должен ловить CTRL + C, попробуйте поймать его вывод. Если функция С ничего не возвращает, то есть не так много можно сделать, кроме как попросить автора добавить обработку исключений, коды возврата и т.д.

try: 
    #Doing something proprietary ... 
    #catch the function call output 
    result = yourCFuncCall() 

    #raise an exception if it's not what you expected 
    if result is None: 
     raise ValueError('Unexpected Result') 

except KeyboardInterupt: 
    print('Must be a CTRL+C') 
    return 

except: 
    print('Unhandled Exception') 
    raise 
+0

Когда я нажимаю Ctrl-C, скрипты выходят без печати ничего на консоль. Как я могу захватить трассировку и т. Д.? – c00kiemonster

+0

Я запускал скрипт с 'python -i script.py', но ничего не делал, когда я нажимал' Ctrl-C'. Любые другие способы получить больше информации о том, что происходит? – c00kiemonster

+0

Я пробовал все это. Еще одно и то же. Спасибо, в любом случае. – c00kiemonster

 Смежные вопросы

  • Нет связанных вопросов^_^