مهمترین آرگومانی که همه فراموش میکنند
فایل روی دیسک فقط بایت است. برای تبدیل بایت به متن (و برعکس) باید کدگذاری (encoding) مشخص شود. اگر آن را ننویسید، پایتون از کدگذاری پیشفرض سیستمعامل استفاده میکند؛ در لینوکس و مک UTF-8 است، اما در ویندوز با تنظیمات منطقهای فارسی معمولاً cp1256 (کدگذاری قدیمی عربی ویندوز). نتیجه: کدی که روی لپتاپ شما درست کار میکند روی سرور لینوکسی فارسی را خراب میکند یا UnicodeDecodeError میدهد. قاعدهی بیاستثنا:
هر open متنی، encoding="utf-8" صریح دارد.
from pathlib import Path
notes = Path("notes.txt")
with open(notes, "w", encoding="utf-8") as f:
f.write("سفارش KSH-101 ثبت شد\n")
print("ارسال به کاشان", file=f) # print هم میتواند در فایل بنویسد
with open(notes, encoding="utf-8") as f:
for line_no, line in enumerate(f, start=1):
print(line_no, line.rstrip("\n"))
with: بستن تضمینی
فایل باز منبع سیستمعامل است و باید بسته شود. بلوک with تضمین میکند فایل در پایان بلوک بسته شود، حتی اگر وسط کار خطا رخ دهد. بدون with، اگر خطایی بین open و close پیش بیاید، فایل باز میماند؛ در ویندوز فایل باز قفل است و نه میتوانید حذفش کنید، نه اکسل میتواند آن را بنویسد.
حالتهای باز کردن
| حالت | معنی | اگر فایل وجود داشته باشد |
|---|---|---|
"r" | خواندن (پیشفرض) | باز میشود؛ اگر نباشد FileNotFoundError |
"w" | نوشتن | محتوا بدون هشدار پاک میشود |
"a" | افزودن به انتها | حفظ میشود؛ متن به انتها اضافه میشود |
"x" | ساخت انحصاری | FileExistsError؛ جلوی بازنویسی تصادفی را میگیرد |
"rb" / "wb" | باینری (تصویر، PDF) | بدون encoding؛ با bytes کار میکند |
خواندن فایل بزرگ
f.read() کل فایل را یکجا در حافظه میآورد. برای فایل لاگ چند گیگابایتی، روی خود شیء فایل حلقه بزنید (مثل مثال بالا)؛ پایتون خطبهخط میخواند و حافظه ثابت میماند.
وقتی کدگذاری فایل را نمیدانید
فایلی که از یک نرمافزار حسابداری قدیمی یا Notepad ویندوز ۷ آمده، احتمالاً cp1256 است. اول با UTF-8 امتحان کنید و اگر خطا داد، با encoding="cp1256" بخوانید و خروجی را UTF-8 ذخیره کنید. پارامتر errors="replace" بهجای خطا، کاراکترهای خراب را با � جایگزین میکند؛ برای «یک نگاه سریع» خوب است، برای دادهی واقعی نه.
نکتههایی که کمتر کسی میداند
- اجرای پایتون با
py -X utf8 script.pyیا تنظیم متغیر محیطیPYTHONUTF8=1پیشفرض همهی open ها را UTF-8 میکند؛ طبق PEP 686 این رفتار در نسخههای آیندهی پایتون پیشفرض میشود. py -X warn_default_encoding script.pyهر open بدون encoding را با هشدار EncodingWarning به شما نشان میدهد؛ روش سریع پیدا کردن همهی جاهای خطرناک.- پایتون در حالت متنی
\r\nویندوزی را هنگام خواندن به\nتبدیل میکند و هنگام نوشتن در ویندوز برعکس؛ اگر فایل برای لینوکس است،newline="\n"بدهید. f.writeخط جدید اضافه نمیکند؛print(..., file=f)اضافه میکند.writelinesهم با وجود نامش خط جدید نمیگذارد.- بعد از
open(..., "w")حتی اگر هیچ چیزی ننویسید، فایل قبلی خالی شده است؛ برای ذخیرهی امن، در فایل موقت بنویسید و بعد باPath.replaceجایگزین کنید.