我想在我的脚本中实现正确的SIGINT处理,它会打开多个文件和数据库连接。如果脚本是CTRL + C'd或以其他方式中断,则应关闭这些。
以前我使用KeyboardInterrupt
异常来捕获CTRL + C,我检查了文件/连接是否已定义,如果是这样,则关闭它们,然后退出。
这真的是pythonic方式吗,还是更好地建议使用信号处理程序? e.g。
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()
对我来说这似乎是 clean ,但我不知道如何将文件名或数据库连接传递给处理程序。
答案 0 :(得分:4)
我宁愿在主线程上捕获KeyboardInterrupt
异常。 KeyboardInterrupt
是python的默认SIGINT
处理程序的结果。 KeyboardInterrupt
异常的异常处理程序比直接捕获SIGINT
时更安全/友好的上下文。
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
cleanup()
编辑:以下是如何在两种方法之间共享变量(状态):
<强>程序:强>
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()
面向对象(我的偏好):
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()
答案 1 :(得分:1)
我的建议是使用signal
库来处理信号。信号不是例外,它们是操作系统的Inter Process Communication(IPC)基础结构的一部分。
信号可以帮助您与程序通信,例如重新加载配置文件,在日志轮换期间关闭日志文件处理程序等等。像apache这样的大部分守护进程都会给它带来麻烦。
Shell脚本具有trap
命令来处理信号并根据捕获的信号采取适当的操作。
通常,python会在退出时自动关闭所有文件处理程序和数据库连接。但为了安全起见,我们可以有一个函数来隐式处理它们。
下面的代码会捕获SIGINT并正确关闭文件。
import signal
import sys
die = False
def handler(signum, frame):
global die
print('Got SIGINT.')
die = True
def closeFile(fh):
fh.flush()
fh.close()
signal.signal(signal.SIGINT, handler)
fh = open('/tmp/a.txt', 'w')
while True:
data = input('> ')
if data == 'q':
closeFile(fh)
break
else:
fh.write(data + '\n')
if die:
closeFile(fh)
print('Completed cleanup.. ')
sys.exit()