https://docs.python.org/3.6/library/subprocess.html#replacing-os-system声明os.system()
可以替换为subprocess.call(…, shell=True)
,但我注意到用它们调用Python程序时存在两个不同之处:
atexit
时,不会触发 subprocess
。
KeyboardInterrupt
时, subprocess
未被确认。
我认为这与子进程的信号处理方式有关,但使用restore_signals=True
或restore_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
)未执行。