信号处理程序退出,但程序继续运行?

时间:2009-08-12 07:38:17

标签: python

显然当我的信号处理程序退出时,我的程序继续运行。即使在“完成日志,现在关闭”之后引发的异常也是如此。 有人可以解释为什么会这样吗?注意功能已经简化

^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')

3 个答案:

答案 0 :(得分:1)

我不认为您的代码仍在运行。尽管它在代码中的位置,但不保证在最终打印消息之前出现异常输出。异常输出转到STDERR,但是您的print语句将转到STDOUT;在这个例子中,两者恰好都写入了相同的终端设备。这两个是独立缓冲的,因此输出顺序不是强制性的;即你无法从输出的相对位置推断出任何东西。

如果将print语句放入单元测试中,您可以在单元测试框架中看到相同的现象。

答案 1 :(得分: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)。

答案 2 :(得分:0)

如果在按下^ C时正在进行的代码周围有一个try / except块,它将无法工作,因为exit()实际上会引发异常。见http://bugs.python.org/issue8021

即使try块不在您自己的代码中,也在您正在调用的库代码中,这也成立。在我正在编写的机器人循环中使用urllib2.urlopen时,我注意到了这一点; urllib2的do_open()例程在尝试连接到URL的代码周围使用try / except。