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

4 浏览
0 Comments

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

我有一个信号处理程序来处理ctrl-c中断。如果在信号处理程序中,我想读取在我的主脚本中设置的变量,是否有不使用"global"语句的替代方法?

我不介意这样做,但在这篇帖子中(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()

0
0 Comments

在上述代码中,问题的原因是信号处理程序(signal handler)被定义在主函数(main_function)之外。这样做没有一个好的理由,所以需要将其移动到主函数中。

解决方法是将信号处理程序定义为主函数的内部函数,并在主函数中设置信号处理函数。这样,信号处理程序可以访问并修改主函数中的局部变量。

以下是修改后的代码示例:

import signal
import sys
import time
def main_function():
    data_for_signal_handler = 10
    def signal_handler(*args):
        nonlocal data_for_signal_handler
        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()

在修改后的代码中,信号处理程序(signal_handler)使用了`nonlocal`关键字来引用主函数(main_function)中的局部变量`data_for_signal_handler`。这样就可以在信号处理程序中访问和修改该变量。

通过将信号处理程序定义为主函数的内部函数,并使用`nonlocal`关键字来引用主函数中的局部变量,解决了在信号处理程序中使用变量的问题,而无需将变量设为全局变量。

0
0 Comments

在面向对象的编程范式中,使用lambda函数非常方便。使用lambda函数可以传递一些额外的上下文(比如self引用),并且可以摆脱未使用的参数(signal和frame)。

上面的代码是一个简单的应用程序,其中包含一个signal_handler函数。在初始化Application对象时,使用signal.signal函数将SIGINT信号与lambda函数绑定。lambda函数在接收到SIGINT信号时调用_signal_handler函数,该函数将self.terminated变量设置为True。

MainLoop函数是一个循环,只有当self.terminated变量为False时才会执行。循环中每隔3秒打印一条消息。直到self.terminated变量为True,循环才会终止。

当运行这段代码时,我们可以看到应用程序在终止之前会一直输出消息。当我们按下CTRL+C时,应用程序接收到SIGINT信号,lambda函数被调用,将self.terminated变量设置为True。然后MainLoop函数检测到self.terminated为True,循环结束,应用程序终止。

原因:

问题是在信号处理程序中使用了lambda函数,并且该lambda函数使用了self引用。由于lambda函数是在初始化对象时创建的,它没有访问对象的上下文,因此无法使用self引用。这导致在信号处理程序中无法正确访问和操作对象的属性。

解决方法:

为了解决这个问题,我们可以使用一个全局变量来存储对象的引用,然后在lambda函数中使用这个全局变量。

下面是修改后的代码:

import time
import signal
class Application:
    def __init__( self ):
        signal.signal( signal.SIGINT, lambda signal, frame: signal_handler() )
        self.terminated = False
    def signal_handler():
        global app
        app._signal_handler()
    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()
global app
app.MainLoop()
print( "The app is terminated, exiting ..." )

在修改后的代码中,我们在signal_handler函数中使用了一个全局变量app,该变量存储了Application对象的引用。然后在lambda函数中调用signal_handler函数,通过全局变量app来访问和操作对象的属性。这样就可以正确地在信号处理程序中使用对象的属性了。

通过这种方式,我们可以在信号处理程序中正确地使用对象的属性,实现了在lambda函数中使用self引用的目的。

0
0 Comments

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

在上面的代码中,我们定义了一个信号处理函数signal_handler和一个主函数main。在主函数中,我们定义了一个全局变量g_var,并将其传递给signal.signal函数。

问题的原因是,信号处理函数signal_handler无法直接访问主函数main中定义的局部变量g_var。这是因为信号处理函数是在一个独立的上下文中执行的,与主函数main不在同一个上下文中。

为了解决这个问题,我们可以使用partial函数来创建一个“闭包”。partial函数可以将一个函数与一组固定的参数绑定在一起,并返回一个新的函数。在这种情况下,我们将g_var作为参数传递给partial函数,然后将返回的函数作为信号处理函数传递给signal.signal函数。这样,当信号处理函数被调用时,它将能够访问到g_var这个变量。

解决方法如下:

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

在这个解决方案中,我们首先导入了signal和functools模块。然后,我们定义了信号处理函数signal_handler,它接受三个参数:g_var、signal和frame。在函数中,我们打印出g_var的值。

接下来,我们定义了主函数main,在函数中我们定义了局部变量g_var,并将其传递给partial函数。partial函数将g_var与signal_handler函数绑定在一起,并返回一个新的函数。

最后,我们使用signal.signal函数将返回的函数作为信号处理函数传递给SIGINT信号。这样,当接收到SIGINT信号时,信号处理函数signal_handler将被调用,并打印出g_var的值。

通过使用partial函数,我们成功地解决了在信号处理函数中访问局部变量的问题。现在,信号处理函数能够访问和使用主函数中定义的局部变量g_var了。

0