خیلی از برنامه‌های کوچک تنظیمات را مستقیم در کد می‌نویسند: تم تیره، اندازه فونت، مسیر آخرین فایل. تا وقتی برنامه باز است مشکلی نیست؛ با بستن پنجره آن مقدارها هم می‌روند. راه ساده و استاندارد این است که یک دیکشنری پایتون بسازید و با ماژول json آن را روی دیسک بنویسید و موقع شروع دوباره بخوانید.

طبق صفحهٔ json در مستندات پایتون، json.dump شیء را به صورت متن جیسون روی یک فایل‌مانند می‌نویسد و json.dumps همان متن را به‌صورت رشته برمی‌گرداند. برای خواندن، json.load از فایل و json.loads از رشته کار می‌کنند. ماژول همیشه str می‌سازد، نه بایت؛ پس فایل را در حالت متن باز کنید و معمولاً encoding='utf-8' بگذارید تا fp.write بتواند رشته را بپذیرد.

تنظیمات را در فایل جیسون بنویسید و بخوانید

یک الگوی رایج همین است. اول دیکشنری تنظیمات را بسازید، بعد با حالت نوشتن ذخیره کنید:

import json
data = {"theme": "dark", "font_size": 14, "lang": "fa"}
with open("settings.json", "w", encoding="utf-8") as f:
    json.dump(data, f, ensure_ascii=False, indent=4)

پارامتر indent=4 خروجی را خوانا می‌کند؛ می‌توانید به‌جای عدد یک رشته هم بدهید. با sort_keys=True کلیدهای دیکشنری مرتب می‌شوند و مقایسهٔ دو فایل آسان‌تر است. پیش‌فرض ensure_ascii=True نویسه‌های غیر ASCII را escape می‌کند؛ برای فارسی خوانا در فایل، ensure_ascii=False بگذارید.

برای خواندن همان فایل:

with open("settings.json", "r", encoding="utf-8") as f:
    data = json.load(f)

اگر فایل خراب باشد یا متن معتبر جیسون نباشد، JSONDecodeError رخ می‌دهد. بهتر است آن را بگیرید و یا تنظیمات پیش‌فرض بسازید یا به کاربر بگویید فایل را درست کند. نکتهٔ مهم از مستندات: چند بار dump پشت‌سرهم روی همان فایل، یک سند معتبر جیسون نمی‌سازد؛ این ماژول پروتکل قاب‌بندی نیست. هر بار یا فایل را از نو بنویسید، یا اول همهٔ داده را جمع کنید و یک‌بار ذخیره کنید.

اگر همین الان یک settings.json کوچک با دو سه کلید ساخته‌اید، در دیدگاه بنویسید فارسی را با ensure_ascii=False دیدید یا هنوز escape شده بود. همان یک جمله معمولاً نشان می‌دهد تنظیم encoding درست نشسته یا نه.

چه نوع‌هایی تبدیل می‌شوند

مستندات جدول تبدیل را روشن می‌گوید: دیکشنری به object، لیست و تاپل به array، و True / False / None به true / false / null. رشته و عدد هم مستقیم می‌روند. نوع‌هایی مثل datetime یا کلاس‌های خودتان به‌صورت پیش‌فرض پشتیبانی نمی‌شوند و TypeError می‌گیرید مگر خودتان آن‌ها را به نوع ساده تبدیل کنید؛ مثلاً تاریخ را به رشتهٔ ISO بسپارید و موقع خواندن دوباره بسازید.

اعتبارسنجی سریع و احتیاط با فایل‌های ناشناس

برای دیدن خروجی مرتب یا چک کردن اعتبار، از خط فرمان می‌توانید python -m json را بزنید؛ python -m json.tool هم هنوز کار می‌کند. اگر فایل خیلی بزرگ یا از منبع نامطمئن است، مستندات هشدار می‌دهد که پارس جیسون می‌تواند پردازنده و حافظه را سنگین کند؛ اندازه را محدود کنید و به دادهٔ ناشناس اعتماد نکنید.

جمع‌بندی عملی: تنظیمات را در دیکشنری نگه دارید، یک‌بار با dump و utf-8 بنویسید، موقع شروع با load بخوانید، فارسی را با ensure_ascii=False حفظ کنید، و برای نوع‌های خاص خودتان تبدیل بنویسید. منبع این مطلب همان صفحهٔ json — JSON encoder and decoder در مستندات پایتون ۳ است.

تنظیمات برنامه‌تان را همین حالا در فایل جدا نگه می‌دارید، یا هنوز چند ثابت بالای فایل پایتون دارید که با هر تغییر باید دوباره کد را ویرایش کنید؟