سطح مقدماتی (Beginner Level)
در برنامهنویسی روزمره پایتون، ما معمولاً از دستور import به صورت ایستا (Static) در ابتدای فایل استفاده میکنیم (مانند import math). اما گاهی اوقات نیاز داریم که نام ماژول را به صورت یک رشته (String) دریافت کنیم و آن را در زمان اجرا (Runtime) بارگذاری کنیم، یا یک ماژول را که تغییر کرده است دوباره بارگذاری (Reload) کنیم. اینجاست که کتابخانه استاندارد importlib وارد عمل میشود.
این ماژول پیادهسازی سیستم import پایتون است و ابزارهایی را برای تعامل با آن فراهم میکند.
۱. ایمپورت پویا (Dynamic Import)
سادهترین و پرکاربردترین تابع در این کتابخانه، import_module است. این تابع به شما اجازه میدهد نام ماژول را به عنوان یک رشته متنی بدهید و شیء ماژول را دریافت کنید.
مثال اول: ایمپورت ساده
در این مثال، ماژول math را بدون استفاده از دستور مستقیم import math و تنها با نام آن بارگذاری میکنیم.
مثال دوم: ایمپورت ماژولهای تو در تو (Nested)
شما همچنین میتوانید ماژولهای زیرمجموعه را با استفاده از نقطه (.) فراخوانی کنید.
۲. بارگذاری مجدد ماژول (Reloading)
یکی از ویژگیهای مهم پایتون این است که وقتی یک ماژول یکبار ایمپورت میشود، برای دفعات بعدی در حافظه کش (Cache) میماند و دوباره خوانده نمیشود. اگر شما در حال توسعه یک برنامه باشید و کد یک ماژول را تغییر دهید، ایمپورت مجدد آن تغییری ایجاد نمیکند. برای حل این مشکل از importlib.reload استفاده میشود.
مثال اول: نحوه استفاده از reload
این کد استاتیک است زیرا برای درک عملکرد آن نیاز به تغییر فایل در حین اجرا دارید که در محیط اجرایی ایزوله قابل نمایش نیست.
# Static Code: Concept of reloading a module
import importlib
import my_config # فرض کنید این یک فایل تنظیمات است
# ... برنامه اجرا میشود ...
# ... فایل my_config.py توسط کاربر ویرایش میشود ...
# برای اعمال تغییرات جدید بدون بستن برنامه:
importlib.reload(my_config)
print("Configuration reloaded!")
مثال دوم: تابع کمکی برای ریلود
یک الگوی رایج برای توسعهدهندگان پلاگینها، ساخت تابعی برای بهروزرسانی کدهاست.
# Static Code: Wrapper function for reloading
import importlib
def safe_reload(module_obj):
try:
return importlib.reload(module_obj)
except Exception as e:
print(f"Error reloading {module_obj}: {e}")
return module_obj
سطح پیشرفته (Professional Level)
در سطح پیشرفته، importlib امکانات بسیار قدرتمندی برای تعامل با سیستم فایل، بررسی وجود ماژولها بدون ایمپورت کردن آنها، و بارگذاری فایلهای پایتون از مسیرهای دلخواه (خارج از PYTHONPATH) ارائه میدهد.
۱. بررسی وجود ماژول (Find Spec)
قبل از اینکه سعی کنید ماژولی را ایمپورت کنید (و با خطای ImportError مواجه شوید)، میتوانید با استفاده از importlib.util.find_spec بررسی کنید که آیا آن ماژول در سیستم وجود دارد یا خیر.
مثال اول: بررسی ماژولهای موجود و ناموجود
این کد کاملاً قابل اجراست و نشان میدهد چگونه مشخصات (Spec) یک ماژول را پیدا کنیم.
۲. ایمپورت فایل از مسیر خاص (Import from Source File)
گاهی اوقات نیاز دارید یک فایل .py را از یک مسیر خاص در هارد دیسک بارگذاری کنید که جزو پکیجهای پروژه نیست (مثلاً سیستم پلاگین یا فایل کانفیگ کاربر). برای این کار باید از spec_from_file_location و module_from_spec استفاده کنید.
مثال اول: الگوی بارگذاری از فایل
این کد استاتیک است زیرا به یک فایل فیزیکی در یک مسیر خاص نیاز دارد.
# Static Code: Importing a file from a specific path
import importlib.util
import sys
def import_source_file(file_name, file_path):
# 1. ایجاد Spec (مشخصات) از روی فایل
spec = importlib.util.spec_from_file_location(file_name, file_path)
if spec and spec.loader:
# 2. ساخت ماژول جدید از روی Spec
module = importlib.util.module_from_spec(spec)
# 3. اضافه کردن به sys.modules (اختیاری اما توصیه شده)
sys.modules[file_name] = module
# 4. اجرای ماژول (اینجا کدها اجرا میشوند)
spec.loader.exec_module(module)
return module
return None
# نحوه استفاده:
# loaded_mod = import_source_file("my_plugin", "/home/user/plugins/plugin_v1.py")
# loaded_mod.some_function()
مثال دوم: شبیهسازی بارگذاری ماژول (Interactive)
در اینجا ما فرآیند ساخت یک ماژول از روی Spec را شبیهسازی میکنیم تا مکانیزم داخلی آن را ببینید.
۳. لیزی لودینگ (Lazy Loading)
یکی از تکنیکهای حرفهای برای افزایش سرعت بالا آمدن برنامه (Startup Time)، استفاده از بارگذاری تنبل (Lazy Import) است. در این روش، ماژول تا زمانی که واقعاً استفاده نشود، ایمپورت نمیشود. پایتون در نسخههای جدیدتر ابزارهایی در importlib.util برای این کار ارائه داده است.
مثال اول: مفهوم Lazy Loader
# Static Code: Lazy loading concept
import importlib.util
import sys
def lazy_import(name):
spec = importlib.util.find_spec(name)
loader = importlib.util.LazyLoader(spec.loader)
spec.loader = loader
module = importlib.util.module_from_spec(spec)
sys.modules[name] = module
loader.exec_module(module)
return module
# این ماژول تعریف میشود اما سنگینی بارگذاری آن تا لحظه استفاده به تعویق میافتد
heavy_module = lazy_import("some_heavy_library")