سطح مقدماتی (Beginner Level)
ماژول shelve در پایتون یک ابزار ساده و قدرتمند برای ذخیرهسازی دادهها به صورت پایدار (Persistent) است. اگر با دیکشنریها (Dictionary) در پایتون راحت هستید، کار با shelve برایتان بسیار ساده خواهد بود. این ماژول به شما اجازه میدهد اشیاء پایتون را در یک فایل روی دیسک ذخیره کنید و بعداً دقیقاً مانند یک دیکشنری با استفاده از کلیدها به آنها دسترسی داشته باشید.
در واقع shelve روی ماژول pickle ساخته شده است اما رابط کاربری سادهتری دارد.
۱. ساخت و ذخیرهسازی داده (Basic Operations)
برای شروع کار، باید فایل shelf را با تابع open باز کنید. کلیدها در این "قفسه" (Shelf) حتماً باید از نوع رشته (String) باشند، اما مقادیر میتوانند هر شیء پایتونی (لیست، دیکشنری، عدد و...) باشند.
مثال اول: ساختار کلی (Static)
این کد نشاندهنده نحوه باز کردن و بستن فایل است، اما به خودی خود اجرا نمیشود زیرا ناقص است.
import shelve
# باز کردن یک فایل shelf (اگر وجود نداشته باشد ساخته میشود)
db = shelve.open('my_data')
# عملیات ذخیرهسازی...
# بستن فایل بسیار مهم است
db.close()
مثال دوم: ذخیره و بازیابی دادهها (Interactive)
در این مثال یک فایل میسازیم، دادهها را ذخیره میکنیم و سپس آنها را میخوانیم.
۲. استفاده از Context Manager (دستور with)
مانند کار با فایلهای متنی، بهترین روش برای کار با shelve استفاده از دستور with است. این کار باعث میشود فایل به صورت خودکار بسته شود، حتی اگر در حین اجرای برنامه خطایی رخ دهد.
مثال اول: ذخیرهسازی ایمن (Interactive)
مثال دوم: متدهای دیکشنری (Interactive)
از آنجا که شیء shelf شبیه دیکشنری است، متدهایی مثل keys() و items() نیز در دسترس هستند (هرچند خروجی آنها View Object معمولی نیست و ممکن است نیاز به تبدیل به لیست داشته باشد).
سطح پیشرفته (Professional Level)
در سطح حرفهای، باید با نحوه مدیریت حافظه، پرچمهای باز کردن فایل (Flags) و چالش مهم writeback آشنا شوید. همچنین دانستن محدودیتهای امنیتی shelve حیاتی است.
۱. چالش تغییر دادههای تغییرپذیر (Mutable) و پارامتر writeback
به طور پیشفرض، shelve تغییرات اعمال شده روی اشیاء تغییرپذیر (مثل لیست یا دیکشنری تو در تو) را که قبلاً ذخیره شدهاند، ردیابی نمیکند. این یکی از رایجترین باگها در استفاده از این ماژول است.
مثال اول: باگ رایج (Interactive)
در کد زیر سعی میکنیم یک عدد به لیست اضافه کنیم، اما تغییرات ذخیره نمیشود.
مثال دوم: حل مشکل با writeback=True (Interactive)
با تنظیم writeback=True، ماژول تمام اشیاء خوانده شده را در حافظه کش (Cache) نگه میدارد و در زمان بستن فایل، آنها را مجدداً روی دیسک مینویسد.
نکته فنی: استفاده از writeback=True حافظه رم بیشتری مصرف میکند و زمان بستن فایل (Close) را طولانیتر میکند، زیرا باید تمام اشیاء کش شده را چک و یا بازنویسی کند.
مثال سوم: آپدیت دستی (Static)
اگر نخواهید از writeback=True به دلیل پرفورمنس استفاده کنید، باید داده را پس از تغییر مجدداً به کلید اختصاص دهید:
# روش بهینه برای سیستمهای با بار سنگین بدون writeback
with shelve.open('data') as db:
data = db['mylist'] # کپی در حافظه
data.append(4) # تغییر
db['mylist'] = data # ذخیره مجدد دستی
۲. پرچمهای باز کردن فایل (Flags)
تابع shelve.open پارامتری به نام flag میگیرد که مشابه کار با فایلها در C یا پایتون است:
'c': (پیشفرض) برای خواندن و نوشتن باز میکند (اگر نباشد میسازد).'n': همیشه یک فایل جدید و خالی میسازد (قبلی را بازنویسی میکند).'r': فقط خواندنی (Read-only).'w': برای خواندن و نوشتن (اما فایل باید از قبل وجود داشته باشد).
مثال اول: حالت فقط خواندنی (Static)
استفاده از این حالت زمانی مفید است که میخواهید مطمئن شوید دیتابیس تصادفاً تغییر نمیکند.
import shelve
try:
# اگر فایل وجود نداشته باشد خطا میدهد
with shelve.open('existing_db', flag='r') as db:
print(db['some_key'])
# db['new_key'] = 10 -> این خط خطا ایجاد میکند (ReadOnly)
except FileNotFoundError:
print("Database not found.")
مثال دوم: ساخت دیتابیس جدید (Interactive)
استفاده از flag='n' برای ریست کردن دادهها.
۳. ذخیرهسازی کلاسهای سفارشی (Custom Objects)
از آنجا که shelve از pickle استفاده میکند، میتوانید کلاسها و نمونههای (Instances) ساخته شده توسط خودتان را نیز ذخیره کنید. فقط باید مطمئن شوید که تعریف کلاس در زمانی که دادهها خوانده میشوند، در دسترس باشد.
مثال اول: ذخیره آبجکت (Interactive)
۴. امنیت و محدودیتها
ماژول shelve ایمن نیست. هرگز فایلی که از منبع ناشناس دریافت کردهاید را با shelve باز نکنید. از آنجا که این ماژول کدهای پایتون را (از طریق pickle) اجرا میکند، یک فایل مخرب میتواند کدهای خطرناک روی سیستم شما اجرا کند.
همچنین shelve از دسترسی همزمان (Concurrency) پشتیبانی نمیکند. اگر دو برنامه (یا دو ترد) همزمان سعی کنند در یک فایل shelf بنویسند، فایل دیتابیس خراب (Corrupt) خواهد شد.
مثال (Static): هشدار امنیتی
# هرگز این کار را با فایل دانلودی از اینترنت انجام ندهید!
import shelve
# خطر اجرای کد مخرب هنگام لود شدن دادهها وجود دارد
# db = shelve.open('suspicious_file.db')