Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否可以防止python在块结束之前终止?_Python_Python 3.x_Signals_Atomic - Fatal编程技术网

是否可以防止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次迭代 我相信这可以通过一个

基本上,我很好奇是否可以“原子地”执行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次迭代

我相信这可以通过一个定制的信号处理器来完成

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