atexit — 종료 처리기¶
The atexit module defines functions to register and unregister
exit handlers: functions that are automatically executed
“at exit”, that is, upon normal program termination (for instance,
if sys.exit() is called or the main module’s execution completes)
or, more generally, upon interpreter shutdown.
종료 시, 모든 등록된 종료 처리기는 등록된 순서의 역순 으로 호출됩니다. 만약 A, B, C 를 등록했다면, 인터프리터 종료 시 C, B, A 순으로 실행됩니다. 이는 하위 수준의 모듈이 일반적으로 상위 수준의 모듈보다 먼저 임포트되므로 나중에 정리되어야 한다는 가정에 기반합니다.
종료 처리기 실행 중 예외가 발생하면(SystemExit 이 발생하지 않는 한) 트레이스백이 출력되고 예외 정보가 저장됩니다. 모든 종료 처리기가 실행된 후, 마지막으로 발생한 예외가 다시 발생합니다.
여러 인터프리터를 사용하는 프로그램에서 각 인터프리터는 고유한 종료 처리기 스택을 가지며, 이는 인터프리터가 종료될 때(예: concurrent.interpreters.Interpreter.close() 또는 C API Py_EndInterpreter() 호출 시) 실행됩니다. 이 모듈의 등록 함수는 호출된 해당 인터프리터에만 영향을 미칩니다.
참고: 프로그램이 파이썬에서 처리하지 않는 시그널에 의해 종료되거나, 파이썬의 치명적인 내부 오류가 감지되거나, os._exit() 가 호출될 때는 종료 처리기가 호출되지 않습니다.
참고: 정리 함수 내부에서 함수를 등록하거나 해제하는 동작은 정의되지 않습니다.
경고
종료 처리기, 특히 C API 확장 기능을 작성할 때는 여러분이 정리 작업을 마친 후에도 다른 종료 처리기가 임의의 파이썬 코드를 실행할 수 있음을 유의하십시오. 해당 코드는 충돌을 일으키는 대신 성공하거나 예외와 함께 실패해야 합니다.
버전 3.12에서 변경: 종료 처리기 내에서 새 스레드를 시작하거나 os.fork() 를 통해 새 프로세스를 생성하려고 하면 이제 RuntimeError 가 발생합니다. 이전에는 메인 파이썬 런타임 스레드가 스레드 상태를 해제하는 동안 내부 threading 루틴이나 새 프로세스가 해당 상태를 사용하려고 시도하면서 레이스 컨디션(race condition)이 발생할 수 있었으며, 이는 깔끔한 종료 대신 충돌을 유발할 수 있었습니다.
버전 3.7에서 변경: 서브 인터프리터와 함께 사용할 경우, 등록된 함수는 등록된 인터프리터에 국한됩니다.
- atexit.register(func, *args, **kwargs)¶
func 를 종료 처리기로 등록합니다. func 에 전달할 선택적 인자는
register()에 인자로 전달해야 합니다. 동일한 함수와 인자를 여러 번 등록할 수 있습니다.이 함수는 func 을 반환하므로 데코레이터로 사용할 수 있습니다.
- atexit.unregister(func)¶
Remove func from the list of exit handlers.
unregister()silently does nothing if func was not previously registered. If func has been registered more than once, every occurrence of that function in theatexitcall stack will be removed. Equality comparisons (==) are used internally during unregistration, so function references do not need to have matching identities.
atexit 예제¶
다음의 간단한 예제는, 모듈이 임포트 될 때 파일에서 카운터를 읽고 프로그램이 종료할 때 프로그램의 명시적인 호출에 의존하지 않고 카운터의 변경된 값을 자동으로 저장하는 방법을 보여줍니다.:
try:
with open('counterfile') as infile:
_count = int(infile.read())
except FileNotFoundError:
_count = 0
def incrcounter(n):
global _count
_count = _count + n
def savecounter():
with open('counterfile', 'w') as outfile:
outfile.write('%d' % _count)
import atexit
atexit.register(savecounter)
위치 및 키워드 인자가 등록된 함수가 호출될 때 전달되도록 register() 에 전달할 수 있습니다:
def goodbye(name, adjective):
print('Goodbye %s, it was %s to meet you.' % (name, adjective))
import atexit
atexit.register(goodbye, 'Donny', 'nice')
# or:
atexit.register(goodbye, adjective='nice', name='Donny')
데코레이터 로 사용하기:
import atexit
@atexit.register
def goodbye():
print('You are now leaving the Python sector.')
이 방법은 인자 없이 호출할 수 있는 함수에서만 작동합니다.