在信号处理程序中使用变量 - 需要全局?

时间:2012-09-11 13:54:40

标签: python

我有一个处理ctrl-c中断的信号处理程序。如果在信号处理程序中我想读取我的主脚本中的变量集,那么在设置变量时是否可以使用“global”语句?

我不介意这样做,但请阅读这篇文章(Do you use the "global" statement in Python?),其中有人评论说没有理由使用全局。

在这种情况下有什么替代方案?

我的代码如下所示:


def signal_handler(signal, frame):
    print "in sig handler - g_var=%s" % g_var

def main():
    global g_var
    g_var = "test"

    time.sleep(120)


if __name__ == '__main__':
    signal.signal(signal.SIGINT, signal_handler)
    main()

5 个答案:

答案 0 :(得分:25)

您可以使用闭包作为从主脚本获取其状态的信号处理程序:

import signal
import sys
import time

def main_function():

    data_for_signal_handler = 10

    def signal_handler(*args):
        print data_for_signal_handler
        sys.exit()

    signal.signal(signal.SIGINT, signal_handler) # Or whatever signal

    while True:
        data_for_signal_handler += 1
        time.sleep(0.5)

if __name__ == '__main__':
    main_function()

答案 1 :(得分:11)

您可以使用partial创建"关闭"。

import signal
from functools import partial

def signal_handler(g_var, signal, frame):
    print "in sig handler - g_var=%s" % g_var

def main():
    g_var = "test"
    signal.signal(signal.SIGINT, partial(signal_handler, g_var))

    time.sleep(120)


if __name__ == '__main__':
    main()

答案 2 :(得分:5)

在面向对象的范例(OOP)中,为此目的使用lambdas非常方便。使用lambdas可以传递一些额外的上下文(比如 self 引用)和/或去除未使用的参数( signal frame )。

import time
import signal

class Application:

    def __init__( self ):
        signal.signal( signal.SIGINT, lambda signal, frame: self._signal_handler() )
        self.terminated = False

    def _signal_handler( self ):
        self.terminated = True

    def MainLoop( self ):        
        while not self.terminated:
            print( "I'm just doing my job like everyone else" )
            time.sleep( 3 )

app = Application()
app.MainLoop()

print( "The app is terminated, exiting ..." )

答案 3 :(得分:1)

您可以从内联定义的函数中访问外部作用域变量,如下所示:

my_values = {'foo':'bar'}
def handler(signum, frame):
    for key,val in my_values.items():
        print key,val
    my_values['bat']='baz'
    #remember to use mutable types, like dicts or lists

signal.signal(signal.SIGINT, handler)

答案 4 :(得分:0)

如果您只是阅读变量,则不需要将变量设为“全局”

def foo():
    print a
a = 3
foo()  #3

global是必要的,允许您更改变量并将该更改传播到模块名称空间。

如果你想在不使用global的情况下将一些状态传递给你的回调,那么我们使用实例方法作为回调的典型方法就是:

class foo(object):
     def __init__(self,arg):
         self.arg = arg
     def callback_print_arg(self):
         print self.arg

def call_callback(callback):
    callback()

a = foo(42)
call_callback(a.callback_print_arg) #42