ماژول atexit پایتون

امیرحسین بیگدلو September 2023

ماژول atexit پایتون یک رابط ساده برای ثبت توابع فراهم می کند تا زمانی که برنامه به طور معمول بسته می شود فراخوانی شود. ماژول sys یک تابع به نام sys.exitfunc را نیز فراهم می کند، اما تنها یک تابع را می توان در آنجا ثبت کرد. رجیستری atexit می تواند توسط چندین ماژول و کتابخانه به طور همزمان استفاده شود.

یک مثال ساده از ثبت یک تابع از طریق atexit.register به شکل زیر است:

import atexit

def all_done():
    print 'all_done()'

print 'Registering'
atexit.register(all_done)
print 'Registered'

از آنجایی که برنامه کار دیگری انجام نمی دهد، تابع all_done بلافاصله فراخوانی می شود:

$ python atexit_simple.py

Registering
Registered
all_done()

 

همچنین امکان ثبت بیش از یک تابع و ارسال آرگومان نیز وجود دارد. این ویژگی می‌تواند برای قطع ارتباط از پایگاه‌های داده، حذف فایل‌های موقت و غیره مفید باشد.

import atexit

def my_cleanup(name):
    print 'my_cleanup(%s)' % name

atexit.register(my_cleanup, 'first')
atexit.register(my_cleanup, 'second')
atexit.register(my_cleanup, 'third')

توجه داشته باشید که ترتیبی که توابع exit فراخوانی می شوند، برعکس ترتیبی است که آنها ثبت می شوند. این ویژگی اجازه می دهد تا ماژول ها به ترتیب معکوس که از آن وارد شده اند پاک شوند، که باعث کاهش تضادهای وابستگی می شود.

$ python atexit_multiple.py

my_cleanup(third)
my_cleanup(second)
my_cleanup(first)

 

# چه زمانی توابع atexit فراخوانی نمی شوند؟

توابع ثبت شده با atexit در موارد زیر فراخوانی نمی شوند:

1. برنامه با ارسال یک سیگنال متوقف شود
2. برنامه با تابع os._exit متوقف شود
3. یک خطای مفسر رخ دهد

برای نشان دادن برنامه ای که از طریق سیگنال متوقف می شود، می توانیم از یک مثال استفاده کنیم. در این مثال دو فایل وجود دارد که یکی برای فرآیند والد و دیگری برای فرآیند فرزند به کار میرود. فرآیند والد، فرآیند فرزند را اجرا کرده، یک مکث ایجاد کرده و در نهایت آن را متوقف میکند:

import os
import signal
import subprocess
import time

proc = subprocess.Popen('atexit_signal_child.py')
print 'PARENT: Pausing before sending signal...'
time.sleep(1)
print 'PARENT: Signaling child'
os.kill(proc.pid, signal.SIGTERM)

فرآیند فرزند یک atexit راه اندازی می کند تا ثابت کند که آن فراخوانی نشده است.

import atexit
import time
import sys

def not_called():
    print 'CHILD: atexit handler should not have been called'

print 'CHILD: Registering atexit handler'
sys.stdout.flush()
atexit.register(not_called)

print 'CHILD: Pausing to wait for signal'
sys.stdout.flush()
time.sleep(5)

وقتی این برنامه را اجرا میکنید خروجی باید به شکل زیر باشد:

$ python atexit_signal_parent.py

CHILD: Registering atexit handler
CHILD: Pausing to wait for signal
PARENT: Pausing before sending signal...
PARENT: Signaling child

توجه داشته باشید که فرآیند فرزند پیام نوشته شده در not_called را چاپ نمی کند.

 

به طور مشابه، اگر برنامه‌ای مسیر خروج عادی را دور بزند، می‌تواند از فراخوانی توابع atexit جلوگیری کند.

import atexit
import os

def not_called():
    print 'This should not be called'

print 'Registering'
atexit.register(not_called)
print 'Registered'

print 'Exiting...'
os._exit(0)

از آنجایی که ما به جای خروج عادی، os._exit() را فراخوانی می کنیم، callback فراخوانی نمی شود.

$ python atexit_os_exit.py

اگر به جای آن از sys.exit() استفاده کرده بودیم، توابع همچنان فراخوانی می شدند.

import atexit
import sys

def all_done():
    print 'all_done()'

print 'Registering'
atexit.register(all_done)
print 'Registered'

print 'Exiting...'
sys.exit()

برنامه را اجرا کنید:

$ python atexit_sys_exit.py

Registering
Registered
Exiting...
all_done()

ویدیوهای مشابه



آموزش duck typing در پایتون
امیرحسین بیگدلو

ارسال نظر


hessam

6 ماه قبل پاسخ به نظر

سلام استاد برنامه ای برای اموزش pyscript داری؟

ارسال نظر



امیرحسین بیگدلو

5 ماه قبل

سلام
اگر وقت کنم یه ویدیو تک قسمتی براش میسازم

hessam

6 ماه قبل پاسخ به نظر

سلام استاد معنی این کد چی میشه؟
print(1j * 2j)

ارسال نظر



امیرحسین بیگدلو

6 ماه قبل

سلام
این کد، داره اعداد پیچیده (complex numbers) رو با هم جمع میکنه

رضا

7 ماه قبل پاسخ به نظر

اقا امیر سلام
ایمیل بتون داده بودم راجب poetry و فایل های makefile و justfile ویدیو بزارین برامون
ممنون میشم اینارم طبط کنین

ارسال نظر



مونگارد