روش ذخیره اطلاعات در پایتون
جلسه دهم - روش ذخیره اطلاعات
مقایسه ذخیرهسازی در فایلها و پایگاه داده، معرفی تابع open()، مودها و مثالهای عملی در پایتون.
مقدمه
در پایتون (و بهطور کلی در علم داده و برنامهنویسی)، حفظ و نگهداری اطلاعات به معنی ذخیره دادهها به شکلی است که بشه بعدها بهراحتی به آنها دسترسی داشت، و در عین حال از امنیت، پایداری و یکپارچگی دادهها محافظت کرد. روشهای مختلفی برای این کار وجود دارند که بر اساس حجم، نوع و اهمیت داده انتخاب میشوند.
ذخیره در فایلها (File Storage)
دادهها مستقیماً در فایلهای سیستم ذخیره میشوند. این روش ساده و مناسب برای پروژههای کوچک است، اما محدودیتهایی نیز دارد که در ادامه بررسی میکنیم.
انواع فایلها
- TXT — ذخیره متن ساده
- CSV — دادههای جدولی (مثل خروجی اکسل)
- JSON — دادههای ساختاریافته با کلید و مقدار
ذخیره در پایگاه داده (Database Storage)
دادهها در قالب جدول، سطر، ستون یا سند در پایگاه داده نگهداری میشوند. پایگاه دادهها برای پروژههای بزرگ و چندکاربره مناسب هستند و امکاناتی مانند تراکنش، ایندکس و بکاپ دارند.
- SQL (ساختیافته): مثل SQLite, MySQL, PostgreSQL
- NoSQL (غیرساختیافته): مثل MongoDB
مزایای ذخیرهسازی در فایلها
-
سادگی و سهولت استفاده
ایجاد و دسترسی به فایلها با توابع استاندارد پایتون (
open(),read(),write()) بسیار ساده است و نیاز به نصب یا پیکربندی نرمافزار جانبی ندارد. -
مناسب برای پروژههای کوچک و تککاربره
حجم داده کم است و نیازی به مدیریت پیچیده و تراکنشهای همزمان وجود ندارد.
-
انعطافپذیری در انتخاب فرمت
میتوان دادهها را به صورت متن ساده، CSV، JSON یا حتی فایلهای باینری ذخیره کرد. هر فرمت قابلیت استفاده در نرمافزارهای دیگر را دارد.
-
قابلیت جابجایی آسان
فایلها قابل کپی، انتقال یا ارسال هستند و میتوانند به راحتی بین سیستمها منتقل شوند.
-
عدم وابستگی به DBMS
برای پروژههای آموزشی یا کوچک که نصب DBMS اضافه سخت است، مناسب است.
معایب ذخیرهسازی در فایلها
- نداشتن ساختار قوی و استاندارد
دادهها معمولاً به صورت خطی یا رشتهای ذخیره میشوند و مدیریت روابط بین آنها دشوار است.
- محدودیت در حجم و عملکرد
خواندن و نوشتن فایلهای بزرگ کند است و جستوجوی پیچیده دشوار میشود.
- عدم پشتیبانی از چندکاربره بودن
دسترسی همزمان چند برنامه یا کاربر میتواند باعث تداخل داده شود؛ مکانیزم تراکنش و قفلبندی ندارد.
- نبود امنیت داخلی
برای امنیت باید به صورت دستی رمزنگاری یا کنترل دسترسی انجام شود.
- عدم تضمین یکپارچگی دادهها
خطر ناسازگاری یا خراب شدن دادهها در پروژههای بزرگ وجود دارد.
- عدم امکان پرسوجوی پیچیده و بهینه
عملیات پیچیده مثل جستوجو و ترکیب دادهها باید دستی پیادهسازی شود.
- نبود ابزار مدیریت و بکاپ حرفهای
بکاپگیری و بازیابی معمولاً با اسکریپت یا ابزار دستی انجام میشود.
مزایای ذخیرهسازی در پایگاه داده
- ساختار و یکپارچگی دادهها
دادهها طبق قواعد مشخص (Constraints) ذخیره میشوند؛ از ناسازگاری جلوگیری میشود.
- تراکنشها و ACID
پایگاه داده از تراکنشهای ACID پشتیبانی میکند: Atomicity, Consistency, Isolation, Durability.
- امنیت و کنترل دسترسی
امکان مدیریت نقشها، رمزنگاری و اتصال امن وجود دارد.
- پشتیبانی از چندکاربره بودن
چندین کاربر همزمان بدون خراب شدن دادهها میتوانند کار کنند.
- سرعت و بهینهسازی جستوجو
با ایندکس و ابزارهای کوئری، پرسوجوها سریع و بهینه اجرا میشوند.
- پشتیبانگیری و بازیابی
ابزارهای حرفهای برای بکاپ و بازیابی وجود دارند.
- مقیاسپذیری
قابلیت مقیاسپذیری عمودی و افقی برای رشد حجم داده و کاربران وجود دارد.
معایب ذخیرهسازی در پایگاه داده
- پیچیدگی نصب و مدیریت
نیاز به نصب، پیکربندی و نگهداری DBMS و زیرساخت دارد.
- هزینه نگهداری
نیاز به منابع سختافزاری و انسانی مثل DBA ممکن است پرهزینه باشد.
- پیچیدگی مقیاسپذیری
در دیتابیس رابطهای بهخصوص مقیاسپذیری افقی پیچیده است.
- تاخیر در همگامسازی
در سیستمهای توزیعشده هماهنگی بین نودها ممکن است باعث تاخیر شود.
- پیچیدگی تراکنش در NoSQL
بعضی پایگاههای NoSQL تراکنش ACID کامل ندارند و نیاز به مدیریت دستی وجود دارد.
- نیاز به طراحی مدل داده
قبل از شروع باید مدل داده طراحی شود و تغییرات در ساختار بزرگ مشکلساز است.
- وابستگی به DBMS
مهاجرت بین سیستمها ممکن است زمانبر و دشوار باشد.
تابع open() در پایتون
تابع open() یکی از پرکاربردترین توابع داخلی پایتون است و برای باز کردن
فایلها جهت خواندن، نوشتن یا افزودن داده استفاده میشود.
file_object = open(file, mode='r', encoding=None)
- پارامتر file
- مسیر فایل (نسبی یا مطلق).
- پارامتر mode
- حالت باز کردن فایل: 'r', 'w', 'a', 'x', ترکیب با 'b' یا 't' و '+' برای خواندن/نوشتن.
- پارامتر encoding
- نوع رمزگذاری فایل متنی مانند 'utf-8'.
مودها و متدهای خواندن/نوشتن
مود 'r' — خواندن
فایل فقط برای خواندن باز میشود و باید از قبل وجود داشته باشد.
with open("example.txt", "r", encoding="utf-8") as f:
content = f.read()
print(content)
متدهای خواندن
read()— خواندن کل محتوا به صورت رشتهreadline()— خواندن یک خطreadlines()— خواندن همه خطوط و برگرداندن لیست
مود 'w' — نوشتن
فایل را برای نوشتن باز میکند؛ اگر فایل وجود داشته باشد محتوای قبلی پاک میشود.
with open("example.txt", "w", encoding="utf-8") as f:
f.write("Hello World!\n")
f.write("This is a new line.\n")
متد write()
فقط رشته قابل نوشتن است؛ برای نوشتن انواع دیگر باید از str() استفاده
کنید.
مودهای دیگر: 'a', 'x', 'b', 't', '+' و ترکیبی
- 'a' — افزودن در انتهای فایل (append)
- 'x' — ایجاد فایل جدید به صورت انحصاری (خطا اگر وجود داشته باشد)
- 'b' — حالت باینری
- 't' — حالت متنی
- '+' — خواندن و نوشتن همزمان
استفاده از with برای مدیریت خودکار فایل
استفاده از بلوک with توصیه میشود تا فایل پس از پایان عملیات بهصورت
خودکار بسته شود، حتی اگر خطایی رخ دهد.
with open("example.txt", "r", encoding="utf-8") as f:
content = f.read()
# بعد از اینجا فایل خودکار بسته شده است
مزایا: نیازی به فراخوانی مستقیم close() نیست و در صورت
بروز استثنا فایل بسته میشود.
مثالها
خواندن همه متن از فایل
with open("notes.txt", "r", encoding="utf-8") as f:
text = f.read()
print(text)
افزودن خط به فایل (append)
with open("log.txt", "a", encoding="utf-8") as f:
f.write("New log entry\n")
خواندن خط به خط
with open("bigfile.txt", "r", encoding="utf-8") as f:
for line in f:
process(line)
نوشتن JSON
import json
data = {"name": "Ali", "age": 30}
with open("data.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
مثال ساده با SQLite
import sqlite3
conn = sqlite3.connect('example.db')
cur = conn.cursor()
cur.execute('CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)')
cur.execute('INSERT INTO users (name) VALUES (?)', ('Ali',))
conn.commit()
conn.close()
💡 تمرینها و سوالات
سوال 1: نوشتن و خواندن متن ساده
یک فایل متنی به نام "greeting.txt" بسازید و متن "سلام، دنیای پایتون!" را در آن بنویسید، سپس محتوای آن را بخوانید.
# خروجی: سلام، دنیای پایتون!
# راه حل:
# نوشتن در فایل
with open("greeting.txt", "w", encoding="utf-8") as f:
f.write("سلام، دنیای پایتون!")
# خواندن از فایل
with open("greeting.txt", "r", encoding="utf-8") as f:
content = f.read()
print(content)
نکته آموزشی: استفاده از with تضمین میکند که
فایل بعد از اتمام کار خودکار بسته میشود. پارامتر encoding="utf-8" برای پشتیبانی از فارسی ضروری است.
سوال 2: افزودن به انتهای فایل
فایل "log.txt" را ایجاد کنید و دو خط لاگ مختلف را به آن اضافه کنید (بدون حذف محتوای قبلی).
# خط اول: "2024-01-01: Start"
# خط دوم: "2024-01-02: Processing"
# راه حل:
with open("log.txt", "a", encoding="utf-8") as f:
f.write("2024-01-01: Start\n")
with open("log.txt", "a", encoding="utf-8") as f:
f.write("2024-01-02: Processing\n")
# خواندن برای نمایش
with open("log.txt", "r", encoding="utf-8") as f:
print(f.read())
نکته آموزشی: مود 'a' (append) محتوای قبلی را حفظ
میکند و فقط به انتهای فایل اضافه میکند. برای فایلهای لاگ بسیار مفید است.
سوال 3: خواندن خط به خط
فایلی با چند خط متن دارید. هر خط را جداگانه بخوانید و با شماره خط چاپ کنید.
# خروجی:
# خط 1: اولین خط
# خط 2: دومین خط
# راه حل:
# ایجاد فایل نمونه
with open("lines.txt", "w", encoding="utf-8") as f:
f.write("اولین خط\nدومین خط\nسومین خط\n")
# خواندن خط به خط
with open("lines.txt", "r", encoding="utf-8") as f:
for i, line in enumerate(f, 1):
print(f"خط {i}: {line.strip()}")
نکته آموزشی: استفاده از حلقه روی شیء فایل کارآمدترین روش برای خواندن
فایلهای بزرگ است. strip() کاراکترهای خط جدید را حذف میکند.
سوال 4: بررسی وجود فایل
قبل از خواندن یک فایل، بررسی کنید که فایل وجود دارد یا خیر.
# از ماژول os استفاده کنید
# راه حل:
import os
filename = "test.txt"
if os.path.exists(filename):
with open(filename, "r", encoding="utf-8") as f:
print(f.read())
else:
print(f"فایل {filename} وجود ندارد")
# ایجاد فایل جدید
with open(filename, "w", encoding="utf-8") as f:
f.write("فایل جدید ایجاد شد")
نکته آموزشی: os.path.exists() برای جلوگیری از
خطای FileNotFoundError استفاده میشود. همچنین میتوان از try-except استفاده کرد.
سوال 5: شمارش تعداد خطوط و کلمات
یک فایل متنی داریم. تعداد خطوط، کلمات و کاراکترهای آن را شمارش کنید.
# خروجی: خطوط: 5، کلمات: 23، کاراکترها: 156
# راه حل:
# ایجاد فایل نمونه
with open("sample.txt", "w", encoding="utf-8") as f:
f.write("این یک متن نمونه است.\nبرای تست شمارش.\nخط سوم.")
# شمارش
with open("sample.txt", "r", encoding="utf-8") as f:
content = f.read()
lines = content.split('\n')
words = content.split()
chars = len(content)
print(f"خطوط: {len(lines)}")
print(f"کلمات: {len(words)}")
print(f"کاراکترها: {chars}")
نکته آموزشی: این یک پروژه کوچک مشابه دستور wc در
لینوکس است. برای فایلهای بزرگ بهتر است خط به خط خوانده شود.
سوال 6: کپی کردن محتوای فایل
محتوای یک فایل را به فایل دیگری کپی کنید.
# source.txt → destination.txt
# راه حل:
# ایجاد فایل مبدا
with open("source.txt", "w", encoding="utf-8") as f:
f.write("این متن برای کپی است.")
# کپی کردن
with open("source.txt", "r", encoding="utf-8") as source:
with open("destination.txt", "w", encoding="utf-8") as dest:
dest.write(source.read())
# تأیید
with open("destination.txt", "r", encoding="utf-8") as f:
print(f.read())
نکته آموزشی: برای فایلهای بزرگ بهتر است به صورت chunk به chunk کپی شود.
همچنین میتوان از shutil.copy() استفاده کرد.
سوال 7: ذخیره لیست به صورت CSV
لیستی از دانشجویان (نام، نمره) داریم. آن را در فایل CSV ذخیره کنید.
students = [("علی", 18), ("سارا", 20), ("رضا", 17)]
# راه حل 1: دستی
students = [("علی", 18), ("سارا", 20), ("رضا", 17)]
with open("students.csv", "w", encoding="utf-8") as f:
f.write("نام,نمره\n")
for name, score in students:
f.write(f"{name},{score}\n")
# راه حل 2: با ماژول csv
import csv
with open("students.csv", "w", encoding="utf-8", newline='') as f:
writer = csv.writer(f)
writer.writerow(["نام", "نمره"])
writer.writerows(students)
نکته آموزشی: فرمت CSV برای دادههای جدولی ساده مناسب است. ماژول csv امکانات بیشتری مانند مدیریت کاما در متن دارد.
سوال 8: خواندن CSV و تبدیل به لیست
فایل CSV دانشجویان را بخوانید و به لیست تبدیل کنید.
# خروجی: [('علی', '18'), ('سارا', '20'), ...]
# راه حل:
import csv
students = []
with open("students.csv", "r", encoding="utf-8") as f:
reader = csv.reader(f)
next(reader) # رد کردن سطر عنوان
for row in reader:
students.append((row[0], int(row[1])))
print(students)
# محاسبه میانگین نمرات
average = sum(score for _, score in students) / len(students)
print(f"میانگین نمرات: {average:.2f}")
نکته آموزشی: استفاده از csv.reader برای خواندن
CSV استاندارد است. میتوان از csv.DictReader برای دسترسی آسانتر
استفاده کرد.
سوال 9: ذخیره دیکشنری به JSON
اطلاعات یک کاربر را به صورت JSON در فایل ذخیره کنید.
user = {"name": "علی", "age": 25, "city": "تهران"}
# راه حل:
import json
user = {"name": "علی", "age": 25, "city": "تهران", "skills": ["Python", "SQL"]}
# نوشتن JSON
with open("user.json", "w", encoding="utf-8") as f:
json.dump(user, f, ensure_ascii=False, indent=2)
# خواندن JSON
with open("user.json", "r", encoding="utf-8") as f:
loaded_user = json.load(f)
print(loaded_user)
نکته آموزشی: ensure_ascii=False برای ذخیره صحیح
فارسی ضروری است. JSON برای دادههای ساختاریافته و تبادل داده بین سیستمها مناسب است.
سوال 10: ذخیره لیست دیکشنریها به JSON
لیستی از محصولات را به JSON ذخیره و بارگذاری کنید.
products = [
{"id": 1, "name": "لپتاپ", "price": 15000000},
{"id": 2, "name": "موبایل", "price": 8000000}
]
# راه حل:
import json
products = [
{"id": 1, "name": "لپتاپ", "price": 15000000},
{"id": 2, "name": "موبایل", "price": 8000000},
{"id": 3, "name": "تبلت", "price": 5000000}
]
# ذخیره
with open("products.json", "w", encoding="utf-8") as f:
json.dump(products, f, ensure_ascii=False, indent=2)
# بارگذاری و جستوجو
with open("products.json", "r", encoding="utf-8") as f:
loaded = json.load(f)
expensive = [p for p in loaded if p["price"] > 10000000]
print("محصولات گران:", expensive)
نکته آموزشی: JSON مناسب ذخیره دادههای پیچیده مثل لیست دیکشنریها است. برای کار با API ها بسیار کاربردی است.
سوال 11: مدیریت تنظیمات برنامه با JSON
یک سیستم مدیریت تنظیمات ساده بسازید که تنظیمات را در JSON نگه دارد.
# توابع: load_config(), save_config(), update_config()
# راه حل:
import json
import os
CONFIG_FILE = "config.json"
def load_config():
if os.path.exists(CONFIG_FILE):
with open(CONFIG_FILE, "r", encoding="utf-8") as f:
return json.load(f)
return {"theme": "light", "lang": "fa", "notifications": True}
def save_config(config):
with open(CONFIG_FILE, "w", encoding="utf-8") as f:
json.dump(config, f, ensure_ascii=False, indent=2)
def update_config(key, value):
config = load_config()
config[key] = value
save_config(config)
# استفاده
config = load_config()
print("تنظیمات فعلی:", config)
update_config("theme", "dark")
print("تنظیمات جدید:", load_config())
نکته آموزشی: این الگو برای مدیریت تنظیمات برنامههای کوچک بسیار مفید است. برای پروژههای بزرگ از فرمتهای پیچیدهتر مثل YAML استفاده میشود.
سوال 12: جستوجو در فایل متنی
در یک فایل متنی به دنبال کلمه خاصی بگردید و خطوط حاوی آن کلمه را چاپ کنید.
# جستوجوی کلمه "Python"
# راه حل:
# ایجاد فایل نمونه
with open("notes.txt", "w", encoding="utf-8") as f:
f.write("Python یک زبان قدرتمند است.\n")
f.write("یادگیری برنامهنویسی مهم است.\n")
f.write("Python برای AI مناسب است.\n")
# جستوجو
search_word = "Python"
with open("notes.txt", "r", encoding="utf-8") as f:
for i, line in enumerate(f, 1):
if search_word in line:
print(f"خط {i}: {line.strip()}")
# جستوجوی case-insensitive
with open("notes.txt", "r", encoding="utf-8") as f:
matches = [line.strip() for line in f if search_word.lower() in line.lower()]
print(f"\nتعداد نتایج: {len(matches)}")
نکته آموزشی: این یک پیادهسازی ساده دستور grep
است. برای جستوجوی پیشرفته میتوان از regex استفاده کرد.
سوال 13: ساخت پایگاه داده SQLite ساده
یک پایگاه داده برای ذخیره اطلاعات کتابها بسازید.
# جدول: books (id, title, author, year)
# راه حل:
import sqlite3
# اتصال و ایجاد جدول
conn = sqlite3.connect('library.db')
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS books (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
author TEXT NOT NULL,
year INTEGER
)
''')
# اضافه کردن کتابها
books = [
("گاتسبی بزرگ", "اسکات فیتزجرالد", 1925),
("1984", "جورج اورول", 1949),
("کشتن مرغ مقلد", "هارپر لی", 1960)
]
cursor.executemany('INSERT INTO books (title, author, year) VALUES (?, ?, ?)', books)
conn.commit()
# جستوجو
cursor.execute('SELECT * FROM books WHERE year > 1940')
for row in cursor.fetchall():
print(row)
conn.close()
نکته آموزشی: SQLite پایگاه دادهای است که نیاز به سرور ندارد و برای پروژههای کوچک عالی است. از پارامترهای ? برای جلوگیری از SQL injection استفاده میشود.
سوال 14: CRUD عملیات در SQLite
توابع Create, Read, Update, Delete برای مدیریت کاربران بنویسید.
# مدیریت کامل جدول users
# راه حل:
import sqlite3
class UserDB:
def __init__(self, db_name='users.db'):
self.conn = sqlite3.connect(db_name)
self.cursor = self.conn.cursor()
self.create_table()
def create_table(self):
self.cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE NOT NULL,
email TEXT,
age INTEGER
)
''')
self.conn.commit()
def create_user(self, username, email, age):
self.cursor.execute('INSERT INTO users (username, email, age) VALUES (?, ?, ?)',
(username, email, age))
self.conn.commit()
def read_users(self):
self.cursor.execute('SELECT * FROM users')
return self.cursor.fetchall()
def update_user(self, user_id, email=None, age=None):
if email:
self.cursor.execute('UPDATE users SET email = ? WHERE id = ?', (email, user_id))
if age:
self.cursor.execute('UPDATE users SET age = ? WHERE id = ?', (age, user_id))
self.conn.commit()
def delete_user(self, user_id):
self.cursor.execute('DELETE FROM users WHERE id = ?', (user_id,))
self.conn.commit()
# استفاده
db = UserDB()
db.create_user("ali123", "ali@example.com", 25)
db.create_user("sara456", "sara@example.com", 22)
print("همه کاربران:", db.read_users())
db.update_user(1, age=26)
print("بعد از آپدیت:", db.read_users())
نکته آموزشی: الگوی CRUD پایه مدیریت داده در همه برنامهها است. استفاده از کلاس کد را سازماندهیتر میکند.
سوال 15: بکاپ گرفتن از فایلهای متنی
یک سیستم بکاپ خودکار بسازید که نسخهای از فایل با تاریخ و ساعت ایجاد کند.
# backup_YYYYMMDD_HHMMSS.txt
# راه حل:
import shutil
from datetime import datetime
def backup_file(source_file):
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
backup_name = f"backup_{timestamp}_{source_file}"
shutil.copy2(source_file, backup_name)
print(f"بکاپ ایجاد شد: {backup_name}")
return backup_name
# ایجاد فایل نمونه
with open("important.txt", "w", encoding="utf-8") as f:
f.write("دادههای مهم")
# بکاپ گیری
backup_file("important.txt")
# بکاپ چندین فایل
import os
def backup_directory(directory, backup_dir="backups"):
os.makedirs(backup_dir, exist_ok=True)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
for filename in os.listdir(directory):
if filename.endswith('.txt'):
source = os.path.join(directory, filename)
dest = os.path.join(backup_dir, f"{timestamp}_{filename}")
shutil.copy2(source, dest)
print(f"بکاپ شد: {filename}")
نکته آموزشی: بکاپ خودکار برای حفظ دادهها ضروری است. میتوان از schedule برای اجرای دورهای استفاده کرد.
سوال 16: سیستم لاگ با سطوح مختلف
یک سیستم لاگ با سطوح INFO, WARNING, ERROR بسازید.
# [2024-01-01 10:30:45] INFO: برنامه شروع شد
# راه حل:
from datetime import datetime
class Logger:
def __init__(self, log_file='app.log'):
self.log_file = log_file
def _write_log(self, level, message):
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
log_entry = f"[{timestamp}] {level}: {message}\n"
with open(self.log_file, 'a', encoding='utf-8') as f:
f.write(log_entry)
print(log_entry.strip())
def info(self, message):
self._write_log('INFO', message)
def warning(self, message):
self._write_log('WARNING', message)
def error(self, message):
self._write_log('ERROR', message)
# استفاده
logger = Logger()
logger.info('برنامه شروع شد')
logger.warning('حافظه کم است')
logger.error('خطا در اتصال به پایگاه داده')
# خواندن لاگها
with open('app.log', 'r', encoding='utf-8') as f:
print("\n--- محتوای لاگ ---")
print(f.read())
نکته آموزشی: سیستم لاگ برای دیباگ و مانیتورینگ برنامه ضروری است. در
پروژههای واقعی از ماژول logging استفاده میشود.
سوال 17: تبدیل CSV به JSON
یک فایل CSV شامل اطلاعات محصولات را به JSON تبدیل کنید.
# products.csv → products.json
# راه حل:
import csv
import json
# ایجاد CSV نمونه
with open('products.csv', 'w', encoding='utf-8', newline='') as f:
writer = csv.writer(f)
writer.writerow(['id', 'name', 'price', 'stock'])
writer.writerow([1, 'لپتاپ', 15000000, 5])
writer.writerow([2, 'موبایل', 8000000, 10])
writer.writerow([3, 'تبلت', 5000000, 8])
# تبدیل CSV به JSON
products = []
with open('products.csv', 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for row in reader:
# تبدیل نوع دادهها
row['id'] = int(row['id'])
row['price'] = int(row['price'])
row['stock'] = int(row['stock'])
products.append(row)
# ذخیره JSON
with open('products.json', 'w', encoding='utf-8') as f:
json.dump(products, f, ensure_ascii=False, indent=2)
print("تبدیل انجام شد!")
print(json.dumps(products, ensure_ascii=False, indent=2))
نکته آموزشی: تبدیل بین فرمتها در پروژههای واقعی رایج است. csv.DictReader هر سطر را به دیکشنری تبدیل میکند.
سوال 18: مدیریت فایلهای موقت
فایل موقتی برای پردازش داده ایجاد کنید که بعد از اتمام کار خودکار حذف شود.
# استفاده از tempfile
# راه حل:
import tempfile
import os
# فایل موقت که خودکار حذف میشود
with tempfile.NamedTemporaryFile(mode='w+', delete=True, encoding='utf-8') as temp:
# نوشتن داده
temp.write("دادههای موقت برای پردازش\n")
temp.write("این فایل بعد از بسته شدن حذف میشود\n")
# بازگشت به ابتدا برای خواندن
temp.seek(0)
print("محتوای فایل موقت:")
print(temp.read())
print(f"مسیر فایل موقت: {temp.name}")
print("فایل موقت حذف شد")
# دایرکتوری موقت
with tempfile.TemporaryDirectory() as tmpdir:
print(f"دایرکتوری موقت: {tmpdir}")
# ایجاد فایل در دایرکتوری موقت
temp_file = os.path.join(tmpdir, 'data.txt')
with open(temp_file, 'w') as f:
f.write("داده موقت")
print(f"فایل ایجاد شد: {temp_file}")
print("دایرکتوری و محتویاتش حذف شدند")
نکته آموزشی: فایلهای موقت برای پردازش میانی، کش و تست بسیار مفید هستند و نیاز به مدیریت دستی حذف ندارند.
سوال 19: سیستم کش ساده با فایل
یک سیستم کش بسازید که نتایج محاسبات سنگین را ذخیره کند.
# اگر نتیجه در کش باشد از فایل بخوان، وگرنه محاسبه کن
# راه حل:
import json
import time
import os
CACHE_FILE = 'cache.json'
def load_cache():
if os.path.exists(CACHE_FILE):
with open(CACHE_FILE, 'r') as f:
return json.load(f)
return {}
def save_cache(cache):
with open(CACHE_FILE, 'w') as f:
json.dump(cache, f, indent=2)
def expensive_calculation(n):
"""محاسبه سنگین (شبیهسازی با sleep)"""
print(f"در حال محاسبه برای {n}...")
time.sleep(2) # شبیهسازی تاخیر
return n ** 2
def cached_calculation(n):
cache = load_cache()
key = str(n)
if key in cache:
print(f"نتیجه از کش برگردانده شد: {n}")
return cache[key]
result = expensive_calculation(n)
cache[key] = result
save_cache(cache)
return result
# تست
print("اولین بار (محاسبه واقعی):")
result1 = cached_calculation(10)
print(f"نتیجه: {result1}\n")
print("بار دوم (از کش):")
result2 = cached_calculation(10)
print(f"نتیجه: {result2}")
نکته آموزشی: کش کردن نتایج محاسبات سنگین یا درخواستهای شبکه سرعت برنامه را افزایش میدهد. در پروژههای بزرگ از Redis یا Memcached استفاده میشود.
سوال 20: سیستم مدیریت یادداشت با SQLite و JSON
یک برنامه کامل مدیریت یادداشت بسازید با قابلیت ذخیره در دیتابیس و export به JSON.
# CRUD + Export + Import
# راه حل:
import sqlite3
import json
from datetime import datetime
class NotesApp:
def __init__(self, db_name='notes.db'):
self.conn = sqlite3.connect(db_name)
self.cursor = self.conn.cursor()
self.create_table()
def create_table(self):
self.cursor.execute('''
CREATE TABLE IF NOT EXISTS notes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
content TEXT,
created_at TEXT,
tags TEXT
)
''')
self.conn.commit()
def add_note(self, title, content, tags=None):
created_at = datetime.now().isoformat()
tags_str = ','.join(tags) if tags else ''
self.cursor.execute(
'INSERT INTO notes (title, content, created_at, tags) VALUES (?, ?, ?, ?)',
(title, content, created_at, tags_str)
)
self.conn.commit()
return self.cursor.lastrowid
def get_all_notes(self):
self.cursor.execute('SELECT * FROM notes ORDER BY created_at DESC')
return self.cursor.fetchall()
def search_notes(self, keyword):
self.cursor.execute(
'SELECT * FROM notes WHERE title LIKE ? OR content LIKE ?',
(f'%{keyword}%', f'%{keyword}%')
)
return self.cursor.fetchall()
def export_to_json(self, filename='notes_export.json'):
notes = self.get_all_notes()
notes_list = [
{
'id': n[0], 'title': n[1], 'content': n[2],
'created_at': n[3], 'tags': n[4].split(',') if n[4] else []
}
for n in notes
]
with open(filename, 'w', encoding='utf-8') as f:
json.dump(notes_list, f, ensure_ascii=False, indent=2)
print(f"Export شد به {filename}")
def import_from_json(self, filename):
with open(filename, 'r', encoding='utf-8') as f:
notes = json.load(f)
for note in notes:
self.add_note(note['title'], note['content'], note.get('tags'))
print(f"{len(notes)} یادداشت import شد")
# استفاده
app = NotesApp()
app.add_note("یادآوری", "فردا جلسه مهم دارم", ['کار', 'مهم'])
app.add_note("آموزش Python", "تمرین فایلها را انجام بده", ['آموزش'])
app.add_note("خرید", "نان، شیر، تخممرغ", ['شخصی'])
print("همه یادداشتها:")
for note in app.get_all_notes():
print(f"- {note[1]}: {note[2]}")
print("\nجستوجو 'Python':")
for note in app.search_notes('Python'):
print(f"- {note[1]}")
app.export_to_json()
نکته آموزشی: این یک پروژه کامل است که ترکیبی از دیتابیس و فایل است. شامل CRUD، جستوجو، export و import است — مناسب برای portfolio.
دیدگاهتان را بنویسید