为什么atexit处理程序不是用子进程执行的,而是os.system?

时间:2018-01-10 20:28:53

标签: python subprocess

https://docs.python.org/3.6/library/subprocess.html#replacing-os-system声明os.system()可以替换为subprocess.call(…, shell=True),但我注意到用它们调用Python程序时存在两个不同之处:

    对于内部程序使用 Ctrl - c atexit时,不会触发
  1. subprocess

  2. 在外部程序中使用KeyboardInterrupt时,
  3. subprocess未被确认。

  4. 我认为这与子进程的信号处理方式有关,但使用restore_signals=Truerestore_signals=False没有效果。

    有没有比手动调用atexit._run_exitfuncs()更好的方法?

    测试程序:

    import atexit
    import os
    import subprocess
    import sys
    import time
    
    if int(os.environ.get('RUN_MAIN', 0)):
        atexit.register(lambda: print('atexit inner'))
    
        print('sub, press Ctrl-C')
        try:
            time.sleep(60)
        except KeyboardInterrupt:
            # atexit._run_exitfuncs()
            print('kbd: inner')
    
    else:
        atexit.register(lambda: print('atexit outer'))
    
        print('== with os.system')
        try:
            print(os.system('env RUN_MAIN=1 %s t-atexit.py' % sys.executable))
        except KeyboardInterrupt:
            print('kbd: outer1')
    
        print('== with subprocess.call')
        try:
            subprocess.call(
                ['env', 'RUN_MAIN=1', sys.executable, 't-atexit.py'],
            )
        except KeyboardInterrupt:
            print('kbd: outer2')
    
        print('== with subprocess.call (shell=True)')
        try:
            subprocess.call(
                'env RUN_MAIN=1 %s t-atexit.py' % sys.executable,
                shell=True,
            )
        except KeyboardInterrupt:
            print('kbd: outer3')
    
        print('exit outer')
    

    输出:

    == with os.system                      
    sub, press Ctrl-C
    ^Ckbd: inner
    atexit inner
    0
    == with subprocess.call
    sub, press Ctrl-C
    ^Ckbd: inner
    kbd: outer2
    == with subprocess.call (shell=True)
    sub, press Ctrl-C
    ^Ckbd: inner
    kbd: outer3
    exit outer
    atexit outer
    

    我已经注意到Django的runserver,当它使用(默认)功能重新加载已更改的文件时使用子进程(和线程):在这种情况下,在子进程中安装了atexit处理程序(通过pdbrc)未执行。

0 个答案:

没有答案