是否可以防止python在块结束之前终止?
基本上,我很好奇是否可以“原子地”执行python代码块而不被信号中断 例如,我想在循环中执行操作,比如:是否可以防止python在块结束之前终止?,python,python-3.x,signals,atomic,Python,Python 3.x,Signals,Atomic,基本上,我很好奇是否可以“原子地”执行python代码块而不被信号中断 例如,我想在循环中执行操作,比如: for i in range(100): do_stuff(1) do_stuff(2) do_stuff(3) 但是我想完成所有三个dou-stuff(1),dou-stuff(2),dou-stuff(3)如果dou-stuff(1)设法启动。脚本应该忽略CTRL+C,完成这三条指令,然后在发生SIGINT时终止。不必执行所有100次迭代 我相信这可以通过一个
for i in range(100):
do_stuff(1)
do_stuff(2)
do_stuff(3)
但是我想完成所有三个dou-stuff(1)
,dou-stuff(2)
,dou-stuff(3)
如果dou-stuff(1)
设法启动。脚本应该忽略CTRL+C,完成这三条指令,然后在发生SIGINT时终止。不必执行所有100次迭代
我相信这可以通过一个定制的信号处理器来完成
import signal
def handler(signum, frame):
# wait for the loop iteration finish and exit
线程和同步,但我不知道如何实现它
import threading
import sys
import signal
class atomic_execution:
started = 0
execution_in_progress = threading.Lock()
def __enter__(self):
atomic_execution.execution_in_progress.acquire()
def __exit__(self, type, value, traceback):
atomic_execution.execution_in_progress.release()
def handler(signum, frame):
atomic_execution.execution_in_progress.acquire()
sys.exit(0)
signal.signal(signal.SIGINT, handler)
while True:
with atomic_execution():
print(1)
print(2)
print(3)
不过,我不确定这是否好。这是基本的想法:
import signal
import time
stop = False
def sighandler(*unused):
global stop
print('signal caught')
stop = True
def main():
for i in range(10):
print('a')
time.sleep(0.5)
print('b')
time.sleep(0.5)
print('c')
time.sleep(0.5)
print()
if stop:
print('STOP')
break
if __name__ == '__main__':
signal.signal(signal.SIGINT, sighandler)
main()
我认为为此目的制作一个上下文管理器并不困难:
进入时:
- 保存当前信号处理程序
- 安装自己的处理程序,设置如上面示例中所示的标志
- 恢复原始信号处理程序
- 如果设置了标志,则退出
但是我不喜欢这个想法,因为您希望在循环之前安装一次处理程序,并在每次迭代中多次测试标志。我相信没有办法避免测试标志。它也可以使用
Lock
s或Condition
s,就像我在编辑的答案中所做的那样,但我不知道这是否更好。@asikorski要么内核为您阻止信号-请参阅低级Linux/Unix调用sigprocmask
which阻止/取消阻止信号-要么您需要某种标志(或类似的同步机构)。后者更简单、更便携。
import threading
import sys
import signal
class atomic_execution:
started = 0
execution_in_progress = threading.Lock()
def __enter__(self):
atomic_execution.execution_in_progress.acquire()
def __exit__(self, type, value, traceback):
atomic_execution.execution_in_progress.release()
def handler(signum, frame):
atomic_execution.execution_in_progress.acquire()
sys.exit(0)
signal.signal(signal.SIGINT, handler)
while True:
with atomic_execution():
print(1)
print(2)
print(3)
import signal
import time
stop = False
def sighandler(*unused):
global stop
print('signal caught')
stop = True
def main():
for i in range(10):
print('a')
time.sleep(0.5)
print('b')
time.sleep(0.5)
print('c')
time.sleep(0.5)
print()
if stop:
print('STOP')
break
if __name__ == '__main__':
signal.signal(signal.SIGINT, sighandler)
main()