34

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

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

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

我的代码如下所示:


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()
4

5 回答 5

37

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

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()
于 2012-09-11T14:08:27.553 回答
31

您可以使用它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()
于 2015-07-29T19:06:39.910 回答
10

在面向对象范式 (OOP) 中,为此目的使用 lambda 非常方便。使用 lambdas,您可以传递一些额外的上下文(如引用)和/或摆脱未使用的参数(信号)。

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 ..." )
于 2017-10-18T12:27:16.583 回答
1

If you're just reading the variable, there should be no need to make the variable "global"

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

global is necessary to allow you to change the variable and have that change propagate into the module namespace.

If you want to pass some state to your callback without using global, the typical way to do this us to use an instance method as the callback:

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
于 2012-09-11T13:57:28.977 回答
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)
于 2012-09-11T14:03:38.900 回答