2009-08-12 2 views
2

По-видимому, когда мой обработчик сигнала выходит, моя программа ПРОДОЛЖАЕТСЯ ПРОДОЛЖИТЬ. это видно из исключения, поднятого даже ПОСЛЕ «log Done, close now». Может кто-нибудь объяснить, почему это так? Обратите внимание, что функции были упрощеныОбработчик сигналов выходит, но программа продолжает работать?

^Clog Ctrl-C 
backup State: not_span 328, pos 22, all_cycles 19 
backup backup complete, you may force exit now 
log  Done, close now 
Traceback (most recent call last): 
    File "singleEdger.py", line 219, in <module> 
    mySingleEdger.outputAllCycles() 
    File "singleEdger.py", line 141, in outputAllCycles 
    r = self.returnCycle(self.dfs_tree, self.not_span[self.pos]) 
    File "singleEdger.py", line 72, in returnCycle 
    udfs = nx.Graph(dfs)     # The trick is to make it undirected 
    File "/var/lib/python-support/python2.6/networkx/graph.py", line 86, in __init__ 
    convert.from_whatever(data,create_using=self) 
    File "/var/lib/python-support/python2.6/networkx/convert.py", line 76, in from_whatever 
    "Input is not a correct NetworkX graph." 
networkx.exception.NetworkXError: Input is not a correct NetworkX graph. 

Эти функции для справки

def sigHandler(self, arg1, arg2): 
     out('log', 'Ctrl-C') 
     self.backup() 
     out('log', 'Done, close now') 
     exit() 


    def outputAllCycles(self): 
     while self.pos < len(self.not_span): 
      r = self.returnCycle(self.dfs_tree, self.not_span[self.pos]) 
      if r: 
       self.all_cycles.append(r) 
       for each in r:  # now it's [ (3,4), (5,6) ] 
        each = (sellHash(each[0]), sellHash(each[1])) 
        self.outfo.write(each[0] +'\t'+ each[1]) 
        self.outfo.write('\n') 
       self.outfo.write('\n') 
      self.pos += 1 
     out("singleEdger", "outputAllCycles done") 


    def backup(self): 
     out('backup', 'State: not_span %i, pos %i, all_cycles %i' % (len(self.not_span), self.pos, len(self.all_cycles))) 
     out('backup', 'backup complete, you may force exit now') 

ответ

1

Я не думаю, что ваш код все еще работает. Несмотря на свою позицию в коде, выход исключений не будет отображаться перед окончательным сообщением печати. Выход Exception будет в STDERR, но ваш оператор печати будет STDOUT; в этом примере оба просто записываются на одно и то же терминальное устройство. Оба буферизуются независимо друг от друга, поэтому порядок вывода не требуется; то есть вы не можете вывести ничего из относительного положения выходов.

Вы можете увидеть те же самые явления с рамкой тестирования модулей, если вы разместите заявления печати в своих модульных тестах.

+0

ОК забавная вещь ИНОГДА, это случается, иногда это не так. Так что я действительно не знаю, чему доверять. – 2009-08-12 08:23:33

+0

На самом деле, это смешно, так как я думаю, что это может быть связано с тем, как ОС обрабатывает питон, но я не уверен – 2009-08-12 08:33:31

+0

Также обратите внимание, что исключение SystemExit не приведет к тому, что система выйдет из системы. Если поймать и обработать обработчик исключений, код будет продолжать работать, как будто ничего не произошло. – Cide

0

Что-то еще, о чем вы должны знать, это то, что вам следует избегать длительной обработки (вызов backup() указывает на потенциально длительный процесс) в обработчике сигнала; лучше установить флаг, вернуться из обработчика сигнала, а затем выполнить свою обработку. Причина в том, что (в Python) обработчик сигнала все равно будет зарегистрирован, и любой последующий сигнал того же типа прервет сам обработчик сигнала, заставив его выполнить снова. Возможно, это не так, как вам хотелось бы.

Или вы можете игнорировать сигнал в обработчике, например.

import signal 
def sigHandler(sig, frame): 
    oldHandler = signal.signal(sig, signal.SIG_IGN) 
    backup() # lengthy processing here... 
    signal.signal(sig, oldHandler) 

но обратите внимание, что это будет игнорировать только тот же сигнал - все еще можно прервать другие сигналы. Является ли ваш backup() реентераном?

This discussion on reentrancy имеет отношение к делу, хотя это C и Python немного отличается, например. сигналы не могут быть заблокированы (если вы не используете ctypes).

0

Если во время выполнения кода^C находится блок try/except, то он не будет работать, потому что exit() действительно вызывает исключение. См. http://bugs.python.org/issue8021

Это выполняется, даже если блок try не находится в вашем собственном коде, а в коде библиотеки, который вы вызываете. Я заметил это при использовании urllib2.urlopen в цикле для робота, который я пишу; Процедура do_open() в urllib2 использует try/except вокруг кода, который пытается подключиться к URL-адресу.

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