"atexit" --- 종료 처리기
************************

======================================================================

The "atexit" module defines functions to register and unregister
cleanup functions.  Functions thus registered are automatically
executed upon normal interpreter termination.  "atexit" runs these
functions in the *reverse* order in which they were registered; if you
register "A", "B", and "C", at interpreter termination time they will
be run in the order "C", "B", "A".

**참고:** 이 모듈을 통해 등록된 함수는 다음과 같은 경우 호출되지 않습
니다. 프로그램이 파이썬이 처리하지 않는 시그널에 의해 종료될 때. 파이
썬의 치명적인 내부 에러가 감지되었을 때. "os._exit()" 가 호출될 때.

**Note:** The effect of registering or unregistering functions from
within a cleanup function is undefined.

버전 3.7에서 변경: C-API 서브 인터프리터와 함께 사용될 때, 등록된 함수
는 등록된 인터프리터에 국지적입니다.

atexit.register(func, *args, **kwargs)

   *func* 를 종료 시에 실행할 함수로 등록합니다. *func* 에 전달되어야
   하는 선택적 인자는 "register()" 에 인자로 전달되어야 합니다. 같은
   함수와 인자를 두 번 이상 등록 할 수 있습니다.

   정상적인 프로그램 종료 시에 (예를 들어, "sys.exit()" 가 호출되거나
   주 모듈의 실행이 완료된 경우에), 등록된 모든 함수는 후입선출 순서로
   호출됩니다. 낮은 수준의 모듈은 일반적으로 상위 수준 모듈보다 먼저
   임포트 되기 때문에 나중에 정리해야 한다는 가정입니다.

   종료 처리기의 실행 중에 예외가 발생하면 ("SystemExit"가 발생하지 않
   는다면) 트레이스백이 인쇄되고 예외 정보가 저장됩니다. 모든 종료 처
   리기가 실행될 기회를 얻은 후에, 발생한 마지막 예외를 다시 일으킵니
   다.

   이 함수는 *func* 을 반환하므로 데코레이터로 사용할 수 있습니다.

   경고:

     Starting new threads or calling "os.fork()" from a registered
     function can lead to race condition between the main Python
     runtime thread freeing thread states while internal "threading"
     routines or the new process try to use that state. This can lead
     to crashes rather than clean shutdown.

   버전 3.12에서 변경: Attempts to start a new thread or "os.fork()" a
   new process in a registered function now leads to "RuntimeError".

atexit.unregister(func)

   Remove *func* from the list of functions to be run at interpreter
   shutdown. "unregister()" silently does nothing if *func* was not
   previously registered.  If *func* has been registered more than
   once, every occurrence of that function in the "atexit" call stack
   will be removed.  Equality comparisons ("==") are used internally
   during unregistration, so function references do not need to have
   matching identities.

더 보기:

  모듈 "readline"
     Useful example of "atexit" to read and write "readline" history
     files.


"atexit" Example
================

다음의 간단한 예제는, 모듈이 임포트 될 때 파일에서 카운터를 읽고 프로
그램이 종료할 때 프로그램의 명시적인 호출에 의존하지 않고 카운터의 변
경된 값을 자동으로 저장하는 방법을 보여줍니다.:

   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.')

이 방법은 인자 없이 호출할 수 있는 함수에서만 작동합니다.
