مقدمه
کار کردن با فایل ها تو هر زبانی مهمه. یکی از شیرینی های زبان پایتان همین عه که کار کردن با فایل ها رو خیلی راحت میکنه. به طرز شیرینی همه چیز قابل پیش بینی عه و اصلا نیاز نیست چیز خاصی رو حفظ کنید. همه چیز خودش میاد. مثل یک شعر
باز کردن فایل
اولین گام برای کار کردن با یک فایل باز کردن اون فایله. این کار با تابع open انجام میشه. دقت کن که اگه فایل مد نظرت توی پوشه ای که برنامه داره اجرا میشه نباشه Traceback میده و به همین خاطره که باید ملکه ذهنت کنی از همین الان که داری واسه اولین بار یاد میگیری تابع open رو توی بلوک های 3 گانه try (که در ادامه مشاهده خواهی کرد) قرار بدی:
try: handle = open("names.txt") except: print("File not Found!") else: print("File is opened successfully.")
خوب حالا نوبت به این میرسه که این فایل رو بخونیم! فقط بازکردنش که نشد کار. خوب طبق عادتی که همین پاراگراف بالایی ایجاد کردیم اولش بلوک های 3 های try رو می نویسیم:
try: handle = open("names.txt") except: print("File not Found!") else: print(handle.read())
میشه با استفاده از متد read کل فایل رو یک جا خوند. راه حل دیگری هم هست که به صورت خط به خط خوندن فایله. این طوری:
for line in handle: print(line.strip())
نکته: متد strip آت و آشغال های انتها و ابتدای یک رشته رو (در این جا مصداقش میشه کل خط) پاک میکنه. مثلا space یا line break
اون دوستای عزیزی که comprehension رو هم بلدن می تونن از تکنیک زیر استفاده کنن:
try: file = [line.strip() for x in open('names.txt')] except: print("Not Found")
تو روش اول که کل فایل رو یک جا با استفاده از متد read می خونیم یک رشته پیوسته دریافت میکنیم با کلی line break (منظورم از line break عبارت n\ عه که توی print تفسیر به شکستن خط میشه). مثلا اگه فایل ما این باشه:
bizhan behrad sina hazhir
اگه کل فایل رو با متد read بخونیم حاصلش میشه اینه:
bizhan\nbehrad\nsina\nhazhir
ولی اگه خط به خط بخونیم و هر خطی رو strip کنیم این n\ ها پاک میشن (متد strip رسالتش همین پاک کردن آت و آشغالای اول و آخر یک رشته است). حالا می تونیم توی حلقه for مون خط به خط strip کنیم توی همون جا پرینت بگیریم یا این که کل فایل رو با comprehension تبدیل به یک list کنیم.
باز کردن و خوندن فایل رو یاد گرفتیم. اما پایتان برای اون هایی که سیر نمیشن جزئیات بیشتری هم گذاشته. یک فایل می تونه در ۴ حالت مختلف باز بشه.
برای یادگیری راحت تر همین الان کلمه rawx رو حفظ کن:read, append, write, x
حالت پیش فرض باز کردن یک فایل read هست و در صورتی هم که این حالت رو به تابع open ندیم (همون طوری که تا الان نداده بودیم) ایرادی نداره، چون پیش فرضه. ولی تو این حالت فقط می تونیم مطالب اون فایل رو بخونیم. اگه خاسته باشیم که به فایل چیزی اضافه کنیم یا کلا فایل رو از اول بنویسیم چی؟! اگه فایل وجود قبلی نداشته باشیم و بخایم درستش کنیم چی؟! این جاست که حالت های دیگه مثل a, w و x به کارمون میاد.
حالت a
تو این حالت هر چیزی که با استفاده از متد write به فایل اضافه کنیم به انتهای فایل اضافه میشه (نه به عنوان یک خط جدید بلکه به همون محتوای قبلی چسبیده) و محتوای قبلی بدون تغییر باقی می مونه. اگه میخای خط به خط اضافه کنی می تونی با n\ توی string ای که میخای write بشه مشخص کنی کجا خط بشکنه. (یعنی بره خط بعدی)
try: handle = open('names.txt', 'a') except: print("Not Found") else: handle.write("I have added this line") handle.close()
حالت w
تو این حالت هر چیزی که با متد write بنویسیم روی فایل کل خط های قبلی فایل رو پاک میکنه و به جای اون ها میشینه.
try: handle = open('names.txt', 'a') except: print("Not Found") else: handle.write("The old content is erased and\nyou see a completely new content.") handle.close()
حالت x
تو این حالت اگه فایل وجود نداشته باشه ایجاد میشه و اگه از قبل فایلی با همین نام وجود داشته باشه Traceback براتون میندازه که حالشو ببرین! handle ای که تو این حالت ایجاد میشه مثل حالت a عمل میکنه اگه متد write روش رو صدا بزنین.
try: new_handle = open("new_file.txt","x") except: print("File already exists!") else: new_handle.write("This is the 1st line\nThis is the 2ns line.") new.close()
به عنوان یک عادت خوب (به این عادت های خوب تو جهان برنامه نویسی میگن Best Practices) از همین الان فرهنگ سازی کن واسه خودت (!!!) که وقتی کارت تموم شد handle رو با متد close ببندی. شاید فکر کنی بدون این هم میشه ولی یک روزی یک جایی به حرف من میرسی که بعد ۱ هفته وقت واسه debug پروژه متوجه میشی همین عادت بد نبستن فایله که باگ اصلی برنامت بوده.
UTF-8 vs. Binary
این چهار حالت نحوه رفتار ما با فایل رو مشخص میکنن که آیا میخایم بخونیم، بنویسیم، ایجاد کنیم و ... از منظر دیگری هم میشه به باز کردن فایل ها نگاه کرد و اون منظر باز کردن و خوندن فایل به صورت binary یا text عه. همون طوری که میدونی توی پایتان ۳ همه و همه رشته های UTF-8 هستن و حالت پیش فرض باز کردن یک فایل هم همین حالت text عه که فایل رو به صورت UTF-8 میخونه. در اکثر موارد به خصوص فایل های متنی مثل txt ها همین کافیه ولی مثلا jpeg ها binary هستن و خوندشون به صورت text دردی از ما دوا نمیکنه. برای همین ممکنه که بعد از یکی از اون کاراکتر های رمز rawx کاراکتر دیگری از بین bt بذارین که مشخص کنه این فایل رو به چه منظری بخونیم: binary یا text
حالت پیش فرض پایتان text عه و در واقع هر بار که تابع open رو بدون مشخص کردن rawx یا bt اش صدا میزنیم در حقیقت داریم این کد رو اجرا میکنیم:
handle = open("names.txt","rt")
ولی حالت های دیگری هم قابل تصوره. مثلا اگه یک تصویر jpeg رو با کد زیر باز کنیم:
handle = open("image.jpeg","rb") print(handle.read())
با چیزی این طوری رو به رو میشیم:
\xf50\xa54\xb8\xd4\xa0\xa2^\x0eS\x00\xac\xee\x11a\xfb<\xc0\xe4Z~`\x00F\x1c\xb7s\x17\x9ezK\x08u7\xdeB8\x01O\x11d\x19\xe1\x1e\xfan\xb2\x0f\x0c2\xf0p=Ng\x85\xbd\x92\xb5\xc2\x86\xdacr\x14\x18u\xcc\xc2\x1b\x83\xa3\xc4N\xd01\xc4\xcd\xd5\x1ay\x87\xf2\'\xf2\x همین طوری ادامه دارد. من بخش کوچکیش رو کپی کردم
حالا از ترکیب rawx و bt هشت تا حالت مختلف به دست میاد!
توانایی کار کردن با file ها به خصوص زمانی که درگیر پروژه های بزرگ میشی یک مهارت کلیدی عه. فرض کن می تونی با یک program ساده Python که روی سرور اجرا میکنی هزار تا کار با فایل های قدیمی تلنبار شده انجام بدی. حتی میتونی فایل هایی با پسوند زبان های دیگه درست کنی (مثلا js) و با استفاده از Python برنامه های زبان های دیگه رو تولید کنی!!! این بحث توی Data Visualization به کارت میاد. زمانی که برای نمایش data به HTML و jS نیاز داری ولی پردازش داده است رو با Python انجام دادی. خوشحال میشم من رو به یک کامنت مهمون کنی و نظرت رو درباره مقاله بگی.