如何正确处理SIGINT以关闭文件/连接

Dae*_*hos 4 python signals exit interrupt-handling

我想在脚本中实现适当的SIGINT处理,该脚本将打开多个文件和一个数据库连接。如果脚本是CTRL + C或其他方式中断,则应将其关闭。

以前我用过 KeyboardInterrupt异常捕获CTRL + C,在那里检查了是否定义了文件/连接,如果如此,则关闭它们,然后退出。

这是否真的是pythonic方法,还是建议使用信号处理程序?例如

import signal, sys, time

def handler(signum, frame):
    print("..kthxbye")
    sys.exit(1)

def main():
    signal.signal(signal.SIGINT, handler)
    i = 0
    while True:
        print(i)
        i += 1
        time.sleep(1)

if __name__ == "__main__":
    main()
Run Code Online (Sandbox Code Playgroud)

这对我来说似乎比较干净,但我不知道如何将文件名或数据库连接传递给处理程序。

pas*_*sti 6

我宁愿KeyboardInterrupt在主线程上捕获异常。KeyboardInterrupt是SIGINTpython 默认处理程序的结果。与直接KeyboardInterrupt捕获时相比,异常的异常处理程序是一个更安全/友好的上下文SIGINT。

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        cleanup()
Run Code Online (Sandbox Code Playgroud)

编辑:这是如何在两种方法之间共享变量(状态):

程序:

import sys, time

class SharedState:
    def __init__(self):
        self.var0 = 42
        self.var1 = 'string'

# method 1
shared_variable = 'woof woof'

# method 2: avoiding global declarations in functions
shared_state = SharedState()

def main():
    # In order to write a global variable you need a global
    # declaration otherwise the assignment would create a
    # local variable

    global shared_variable
    shared_variable = 5

    shared_state.var0 = 10

    time.sleep(10)

def cleanup():
    print shared_variable
    print shared_state.var0
    sys.exit(1)

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        cleanup()
Run Code Online (Sandbox Code Playgroud)

面向对象(我的偏爱):

import sys, time

# method 3: object oriented programming
class Program:
    def __init__(self):
        self.var0 = 42
        self.var1 = 'string'

    def main(self):
        self.var0 = 5
        self.var1 = 'woof woof'
        time.sleep(10)

    def cleanup(self):
        # both main and cleanup can access the member
        # variables of this class
        print self.var0
        print self.var1
        sys.exit(1)

    def execute(self):
        try:
            self.main()
        except KeyboardInterrupt:
            self.cleanup()

if __name__ == '__main__':
    Program().execute()
Run Code Online (Sandbox Code Playgroud)