هنر برنامه نویسی با پایتون ، ‌‌‌‌‌فایلها

متغیرها و ساختمان داده های مختلفی چون فهرست[1] ، واژه نامه[2]، چندتایی[3] ، کلاس و دیگر اشیایی  که تا کنون در برنامه ها جهت ذخیره و پردازش اطلاعات استفاده می کردیم در حافظه اصلی[4] رایانه ذخیره می شوند بنابراین با پایان یافتن برنامه یا خاموش شدن دستگاه همه داده ها از بین می روند. برای ذخیره دائمی ، داده ها باید درفایل ها ذخیره شوند.از این رو کار با فایل ها بخش بسیار مهمی از هر برنامه است. فایل یک واحد منطقی در سیستم عامل[5] است که برای نگهداری طولانی مدت اطلاعات برروی رسانه های ذخیره سازی مختلفی چون دیسک سخت[6] ، دیسک های نوری[7] ودیگر رسانه های ویژه نگهداری طولانی مدت اطلاعات استفاده می شود. کار با فایل ها فرآیندی بسیار پیچیده است از این رو مدیریت فایل ها یکی از وظایف بسیار مهم سیستم عامل است. 

 

 فایلها در دوگروه متنی[8] و دودویی[9] دسته بندی می شوند ،درفایل های متنی ، داده ها به صورت رشته (نوع داده str) ذخیره می شوند و به صورت رشته هم خوانده می شوند. به زبان ساده تر واحد خواندن و نوشتن داده ها درفایل های متنی رشته است به همین دلیل است که اطلاعات ذخیره شده در فایل های متنی (برای مثال یک فایل html) قابل چاپ کردن و دیده شدن توسط انسان هستند  یعنی کاربرمی تواند اطلاعات ذخیره شده در یک فایل متنی را به کمک نرم افزار ساده ای چون Notepad در سیستم عامل ویندوز و نرم افزارهای Vim یا Nano در سیستم عامل لینوکس مشاهده کند.

در فایل های متنی ، داده ها در قالب نوع داده ای رشته[10] ذخیره و خوانده می شوند از این رو نوع رمزگذاری[11] متن استفاده شده در این فایلها برای ذخیره صحیح ، خواندن درست و نمایش مناسب داده های ذخیره شده در آن بسیار مهم است، رمزگذاری یونیکدutf-8  یکی از پراستفاده ترین رمزگذاری های مورد استفاده در فایل های متنی است.  برای دیدن نوع رمزگذاری پیش فرض سیستم عامل  می توانید از کد زیراستفاده کنید :

import locale

print(locale.getpreferredencoding(False))

در فایلهای دودویی[12] داده ها به صورت مجموعه ای از بایت ها (نوع داده bytes) ذخیره می شوند و به صورت بایت هم خوانده می شوند به زبان ساده تر واحد خواندن و نوشتن داده ها در فایل های دودویی بایت است. یعنی داده ها به صورت مجموعه ای از بیت های 0 و 1 و در قالب آرایه ای از بایت ها در فایل ذخیره می شوند و به همان صورت هم خوانده می شوند.فایلهای تصویری (برای مثال JPG و BMP )، فایل های صوتی (برای مثال MP3 وWAV ) ، فایلهای ویدئویی (برای مثال MPEG ، DIVX )و فایل های اجرایی (برای مثال EXE و COM ) نمونه هایی از فایلهای دودویی هستند. در زبان برنامه نویسی پایتون برای کار کردن با فایل ها لازم است سه گام اساسی زیربه ترتیب برداشته شوند:

1-    بازکردن فایل با استفاده از تابع open()

2-    انجام عملیات مورد نظر (خواندن ، نوشتن ، به روزرسانی و ...)

3-    بستن فایل

تابع  open()

گل سرسبد توابع و دستورات کاربا فایل ها درپایتون دستور open() است ازاین دستوربرای باز کردن یک فایل استفاده می شود. بازکردن یک فایل به معنای درخواست مفسر پایتون از سیستم عامل برای در اختیار گرفتن آن فایل و اجازه یافتن برای اجرای عملیات مختلفی چون خواندن از فایل یا نوشتن درفایل است اگرتلاش دستورopen برای بازکردن فایل با موفقیت همراه شود یک شی فایل[13] برگردانده می شود که ازآن می توان برای کاربا فایل باز شده استفاده کرد چنانچه تلاش  این دستور برای بازکردن فایل با شکست روبرو شود یک استثنا از نوع OsError رخ می دهد.

 الگوی کلی نگارش و بکار گیری این دستور همانند زیر است :

open(path , mode)

تابع open دارای چندین ورودی ظاهری[14] است که در زیر به دو تا ازمهم ترین آنها پرداخته شده است:

 : path این ورودی مسیردستیابی به فایل شامل نام ومکان ذخیره سازی فایل را مشخص می کند.

 :mode این ورودی نوع عملیات(خواندن ، نوشتن و...) وحالت باز شدن فایل (متنی یا دودویی) را مشخص می کند.

 نوع عملیات ، کاری است که می خواهید پس از باز شدن فایل با آن انجام دهید ، عملیات اصلی به هنگام کار با فایل ها عبارتند از : خواندن  از فایل ، نوشتن  در فایل ، ساخت  فایل جدید ، به روزرسانی  محتوای فایل و افزودن  محتوا به انتهای فایل.

مقدار پیش فرض ورودی mode، بازشدن فایل برای عملیات خواندن در حالت متنی است یعنی اگراز مقداردهی به این ورودی چشم پوشی کنید دستور open نوع عملیات را خواندن وحالت فایل را متنی فرض می کند.

مقدارهای مجاز قابل تخصیص به نوع عملیات و حالت در زیر آمده است :

1-    مقدارهای تعیین کننده نوع عملیات :

r  یعنی باز کردن  فایل برای عملیات خواندن ، این مقدار پیش فرض برای نوع عملیات است.

 w یعنی بازکردن فایل برای عملیات نوشتن، این مقدارمحتوای پیشین فایل را ازبین می برد.چنانچه فایل مورد نظراز قبل وجود نداشته باشد دستورopen آن را خواهد ساخت.

 x یعنی باز کردن فایل برای عملیات ساختن فایل جدید وعملیات نوشتن ، چنانچه فایل مورد نظراز قبل وجود داشته باشد یک استثنا رخ می دهد.

a  یعنی باز کردن فایل برای عملیات افزودن محتوا به انتهای فایل ، چنانچه پیش ازاین فایل مورد نظروجود نداشته باشد دستورopen در ابتدا آن را می سازد.

r+ یعنی بازکردن فایل برای به روزرسانی وانجام همزمان عملیات خواندن ونوشتن، دراین حالت داده های قبلی فایل ازبین نمی روند.

w+ یعنی بازکردن فایل برای به روزرسانی وانجام همزمان عملیات خواندن و نوشتن، دراین حالت داده های قبلی فایل ازبین می روند.

a+ یعنی بازکردن فایل برای به روزرسانی وانجام همزمان عملیات خواندن و افزودن محتوا به انتهای فایل ، دراین حالت داده های قبلی فایل ازبین نمی روند. چنانچه پیش ازاین فایل مورد نظروجود نداشته باشد دستور open آن را خواهد ساخت.

2-    مقدارهای تعیین کننده حالت فایل :

t  یعنی باز کردن فایل در حالت متنی ، این مقدار پیش فرض برای حالت بازکردن فایل است

b  یعنی بازکردن فایل در حالت دودویی

 خواندن فایل

گفتیم که اگرتلاش دستورopen برای بازکردن یک فایل با موفقیت همراه شود یک شی فایل[15]  برگردانده می شود که از آن می توان برای انجام عملیات مورد نیاز برروی فایل استفاده کرد. در زیربه مهمترین شگردهای این شی برای خواندن داده ها از فایل می پردازیم :

1-    شگرد read()

2-    شگرد readline()

3-    شگرد readlines()

 شگردread() ویژه خواندن از فایلی است که برای عملیات خواندن بازشده است این شگرد تنها دارای یک ورودی است که تعداد بایت ها (در حالت دودویی) یا رشته هایی (درحالت متنی) که درهرنوبت فراخوانی آن باید از فایل خوانده شوند را تعیین می کند. چنانچه مقدار این ورودی خالی رها شود و یا یک مقدارمنفی به آن ارسال گردد.شگردread()  تمام محتوای فایل را می خواند و برمی گرداند.

 خروجی این شگرد بستگی به حالت بازشدن فایل دارد ، در حالت متنی خروجی آن رشته ای است به طول n که n همان آرگومان ارسال شده به شگرد است ودرحالت دودویی خروجی آن دنباله ای است از بایت ها به طول n کهn همان آرگومان ارسال شده به شگرد است.

با هربارفراخوانی این شگرد به صورت read(n) تعدادn نویسه[16] یا بایت[17] (بر اساس حالت باز شدن فایل) خوانده شده و برگشت داده می شود با رسیدن به پایان فایل ، شگرد مقدار رشته خالی (‘’ در حالت متنی و b’’در حالت دودویی) را برمی گرداند.

بستن فایل

بازکردن یک فایل با استفاده از دستور open به معنای درخواست مفسر پایتون از سیستم عامل برای در اختیار گرفتن آن فایل و اجازه یافتن برای اجرای عملیات مختلفی چون خواندن از فایل یا نوشتن درفایل است درطول مدتی که مفسرپایتون فایل باز شده را در دست دارد دیگر پردازش  ها نمی توانند به آن دسترسی داشته باشند.فایل ها از منابع محدود و حیاتی سیستم عامل هستند بنابراین بستن فایل یا فایل هایی که به وسیله دستورopen() باز شده اند به معنای آزاد شدن منابع سیستم عامل و بازشدن دست آن برای اختصاص آنها به پردازش های دیگر است. از این رو بستن فایل ها ی باز شده توسط دستورopen پس از پایان عملیات مورد نیازیک رویکرد بسیار خوب برای هربرنامه نویسی است.درپایتون برای بستن فایل بازشده توسط دستورopen از شگرد close()  شی فایل برگشت داده شده استفاده می شود.

مثال : کد زیر فایل country.txt  که درمسیرd:\data\country.txt قراردارد را برای عملیات خواندن ودرحالت متنی بازمی کند)دراین فایل فقط رشته “IRAN”ذخیره شده است( سپس با استفاده از دستور read(1) نویسه به نویسه محتوای آنرا خوانده و چاپ می کند. سرانجام با استفاده از شگردclose() فایل باز شده را می بندد :

country = open("d:\\data\\country.txt","tr")

print(country.read(1))

print(country.read(1))

print(country.read(1))

print(country.read(1))

country.close()

خروجی کد بالا همانند زیر است :

I

R

A

N

مثال : کد مثال بالا با توجه به این که شگرد read() با رسیدن به پایان فایل ، رشته خالی (’’) را برمی گرداند بازنویسی شده است :

country = open("d:\\data\\country.txt","tr")

char = country.read(1)

while char != '':

    print(char)

    char = country.read(1)

country.close()

مثال : کد زیر فایل student.txt  که درمسیرd:\data\student.txt قراردارد را برای عملیات خواندن ودرحالت متنی بازمی کند، شی فایل  بر گشت داده شده را درمتغیرmyfile ذخیره می کند. سپس با استفاده ازشگردread() تمامی محتوای فایل student.txt را خوانده و درخروجی صفحه نمایش چاپ می کندو سرانجام با استفاده ازشگردclose() فایل باز شده را می بندد :

myfile = open("d:\\data\\student.txt","tr")

print(myfile.read())

myfile.close()

با توجه حالت پیش فرض ورودی mode که بازکردن فایل برای عملیات خواندن در حالت متنی است می توان از ارسال مقدار ”tr”به این آرگومان چشم پوشی کرد:

myfile = open("d:\\data\\student.txt")

print(myfile.read())

myfile.close()

چنانچه فایل مورد نظر درپوشه جاری یعنی درکناراسکریپت پایتون ذخیره شده باشد نیازی به نوشتن مسیر کامل دسترسی به فایل نیست وارسال تنها نام فایل به آرگومان path کافی است :

myfile = open("student.txt","tr")

print(myfile.read())

myfile.close()

خواندن خط به خط فایل های متنی

براساس آنچه گفته شد یک فایل متنی را می توان مجموعه ای ازرشته ها دانست که درقالب یک یا چند خط سازماندهی شده اند. بنابراین در فایل های متنی باید راهی برای تشخیص پایان یک خط  وجود داشته باشد به این منظورهرسیستم عامل انتهای یک خط را با نشانه ویژه ای علامت گذاری می کند که به آن علامت پایان خط[18]  گفته می شود. برای نمونه  سیستم عامل ویندوز پایان یک خط را با علامت  [19]CRLF  که همان جفت نویسه“\r\n”  است علامت گذاری می کند در حالی که سیستم عامل لینوکس پایان یک خط را تنها با نویسه LF[20]  که همان نویسه آشنای “\n” است علامت می زند. در زبان برنامه نویسی پایتون برای خواندن خط به خط یک فایل متنی سه روش وجود دارد که در زیر به هریک از آنها پرداخته می شود :

1-    استفاده از حلقه for

مثال :

myfile = open("d:\\data\\student.txt","r")

for line  in myfile:

        print(line)

myfile.close()

2-    استفاده از شگرد readline()

شگردreadline() یک خط از فایل را می خواند ودرقالب یک رشته (str)  برمی گرداند سپس اشاره گر فایل را به ابتدای خط بعدی می برد. این شگرد با رسیدن به انتهای فایل متنی رشته خالی (’’) را برمی گرداند. اگر می خواهید تعداد معینی از رشته های موجود در یک خط از فایل را بخوانید تعداد مورد نظر خود را به عنوان آرگومان به این شگرد ارسال کنید.

مثال:

 myfile = open("d:\\data\\student.txt","r")

line= myfile.readline()

while line != '':   

    print(line)

    line= myfile.readline() 

myfile.close()

3-    استفاده از شگرد readlines()

شگردreadlines() تمامی خطوط موجود در فایل متنی را به یکباره خوانده ودرقالب یکlist برمی گرداند.بنابراین می توان با پیمایش فهرست برگردانده شده به هر خط از فایل دست یافت.

مثال:

myfile = open("d:\\data\\student.txt","r")

list1 = myfile.readlines()

for itm in list1:

    print(itm) 

myfile.close()

 

 

نوشتن در فایل

اگرتلاش دستورopen  برای بازکردن یک فایل با موفقیت همراه شود یک شی فایل[21] برگردانده می شود که از آن می توان برای انجام عملیات مورد نیاز برروی فایل استفاده کرد.درزیربه مهمترین شگردهای این شی برای نوشتن داده ها در فایل می پردازیم :

1-    شگرد write()

2-    شگرد writelines()

 مهم ترین شگرد این شی برای نوشتن داده ها در فایلwrite()  است. این شگرد ویژه نوشتن در فایلی است که برای عملیات نوشتن (w) ، افزودن به انتهای فایل (a) ، ساختن (x)  یا به روزرسانی (+) بازشده است و تنها دارای یک ورودی است که بایت ها (در حالت دودویی) یا رشته ای (درحالت متنی) که باید در فایل نوشته شود را تعیین می کند.

مثال : کد زیر فایل student.txt را برای عملیات افزودن محتوا به انتهای فایل و در حالت متنی باز می کند ، با استفاده از شگرد write() دو خط متن به انتهای فایل اضافه کرده و فایل را می بندد سپس دوباره آنرا برای خواندن بازکرده و محتوای آنرا بر روی صفحه نمایش می دهد:

std = open("d:\\data\\student.txt","a")

std.write("zohre, bahary,20 ,9 ,Shirvan" + "\n")

std.write("nasim, kamai,19 ,12 ,Tehran" + "\n")

std.close()

std = open("d:\\data\\student.txt","r")

print(std.read())

std.close()

 

مثال : کد زیر فایل متنی جدیدی به نام teachers.txt و در مسیر d:\data می سازد با استفاده از شگردwrite() دو خط متن به فایل اضافه کرده و فایل را می بندد سپس دوباره آنرا برای خواندن بازکرده و محتوای آنرا بر روی صفحه نمایش می دهد:

 std = open("d:\\data\\teachers.txt","x")

std.write("zohre, bahary,20 ,9 ,Shirvan" + "\n")

std.write("nasim, kamai,19 ,12 ,Tehran" + "\n")

std.close()

std = open("d:\\data\\teachers.txt","r")

print(std.read())

std.close()

مثال : شبیه سازی دستور copy سیستم عامل ویندوز با نوشتن تابعی به نام pycopy که دارای دو ورودی است، ورودی نخست به نام src مشخص کننده نام و مسیر فایل مبدا است ، ورودی دوم به نام dest مشخص کننده نام و مسیری است که می خواهید فایل مبدا با آن نام و در آن مسیر ذخیره گردد:

 def pycopy(src, dest):

    srcfile = open(src ,"br")

    dstfile = open(dest,"bw")

    buff = 2048

    readedByte = srcfile.read(buff)

    while readedByte != b'':

        dstfile.write(readedByte)

        readedByte = srcfile.read(buff)

    print("file copied")

pycopy("d:\\1\\img1.jpg", "d:\\2\\img2.jpg")

بستن خودکار فایل ها

گفتیم که بازکردن یک فایل با استفاده از دستور open به معنای درخواست مفسر پایتون از سیستم عامل برای در اختیار گرفتن آن فایل و اجازه یافتن برای اجرای عملیات مختلفی چون خواندن از فایل یا نوشتن درفایل است درطول مدتی که مفسرپایتون فایل باز شده را در دست دارد دیگر پردازش  ها نمی توانند به آن دسترسی داشته باشند.فایل ها از منابع محدود و حیاتی سیستم عامل هستند. بنابراین بستن فایل یا فایل هایی که به وسیله دستورopen()  باز شده اند به معنای آزاد شدن منابع سیستم عامل و بازشدن دست آن برای اختصاص آنها به پردازش های دیگر است. از این رو بستن فایل ها ی باز شده توسط دستور open پس از پایان عملیات مورد نیازیک رویکرد بسیار خوب برای هربرنامه نویسی است. اما این تنها دلیل استفاده از دستور close() نیست در حقیقت پایتون با هدف افزایش کارآیی و بهبود سرعت نوشتن داده ها در فایل به صورت پیش فرض از یک حافظه میانی[22] استفاده می کند یعنی به جای نوشتن مستقیم داده ها در دیسک سخت ، ابتدا آنها را به صورت موقت در بخشی از حافظه اصلی جای می دهد و سپس ازروی این حافظه موقت داده ها را برداشته و در فایل می نویسد. حال چنانچه  در بافر داده هایی وجود داشته باشد و برنامه نویس نوشتن دستورclose()  را فراموش کند ممکن است بخشی از داده های منتقل نشده از بافر به دیسک برای همیشه از دست بروند. در حقیقت مفسر پایتون با رسیدن به دستورclose() ابتدا داده های باقی مانده درحافظه موقت میانه را که هنوزدرفایل نوشته نشده اند درفایل می نویسد وسپس فایل را می بندد و این دلیل مهم دیگری برای بستن فایلها پس ازانجام عملیات مورد نیازاست. همچنین گاهی خطا و استثنای رخ داده در برنامه موجب عبور جریان عادی هدایت برنامه از کد مربوط به بستن فایل می شود. در این حالت دستورclose()  هرگز اجرا نخواهد شد برای مثال در کد زیر درصورت رخ دادن خطا در خط سوم که شگردwrite() فراخوانی شده است دستور  myfile.close() اجرا نمی شود :

myfile = open("d:\\data\\student.txt","w")

myfile.write(“Hellow World”)

myfile.close()

بنا بر آنچه گفته شد ، وجود یک رویکرد مناسب برای چیره شدن براین چالش ها و اطمینان ازبسته شدن فایل ضرورتی گریزناپذیر است. درزبان برنامه نویسی پایتون دو شیوه برای حل این مشکل وجود دارد : 1- بکارگیری رهنمون try     2- بکارگیری رهنمون with

بکارگیری رهنمون try

رخ دادن خطا به هنگام کار با فایل ها به دلایل مختلفی چون: خرابی دیسک ، پرشدن فضای دیسک ، حذف فایل ، قفل شدن فایل توسط یک پردازش دیگر، ورود نام و مسیر نادرست برای دسترسی به فایل ویا پدید آمدن شرایطی چون : خرابی سخت افزار پدید می آید و می تواند مسیر عادی جریان برنامه را از حالت طبیعی و پیش بینی شده خارج  و سبب توقف ناخواسته اجرای برنامه وعبور ناخواسته از کد نوشته شده برای بستن درست فایل های باز شده گردد. از این رو استفاده از ساختارtry برای مدیریت و رسیدگی به خطای پیش آمده ضروری است. درحقیقت با قرار دادن دستورclose()  در بخش finally این ساختار می توان از بسته شدن فایل در صورت رخ دادن خطا اطمینان حاصل کرد برای آشنایی بیشتر با این رویکرد و درک بهتر آن  به دو مثال زیر توجه کنید :

مثال : در کد زیر اگردرخط نخست که از دستورopen()  استفاده شده است  استثنایی رخ ندهد و تلاش دستورopen()  برای باز کردن فایل product.txt با موفقیت همراه باشد حتی در صورت رخ دادن خطا به هنگام اجرای دستور write() فایل به درستی بسته خواهد شد.زیرا دستورclose() نوشته شده دربدنه رهنمون finally درهرحال اجرا خواهد شد.

products = open("d:\\data\\product.txt","w")

try:

      products.write("Leyboard,202")

except:  

       print("Error: can not write to file" )

finally:

      products.close()

مثال : در کد زیراز ساختار try تو درتو استفاده شده است بنابراین افزون بر آنکه  احتمال رخ دادن استثنا در دستورwrite() اداره می شود استثنای رخ داده در دستورopen()  هم پوشش داده خواهد شد.

try:

     products = open("d:\\data2\\product.txt","w")

      try:

            products.write("Leyboard,202")

      except:  

            print("Error: can not write to file" )

      finally:

           products.close() 

except:  

       print("Error: can not open file")

در مثال بالا به این نکته ظریف توجه کنید که اگرازساختارtry به صورت تودرتو استفاده نمی کردیم ودستورclose()  را همانند کد زیر در بخش finally  ساختار try تک سطحی می نوشتیم با رخ دادن خطای احتمالی در دستور open() جریان اجرای برنامه سرانجام وارد بخش finally می شد و با اجرای دستورclose()  سعی در بستن فایلی می کرد که پیش از این بازنشده است و این خود موجب اعلام یک استثنای مدیریت نشده توسط مفسر پایتون و توقف برنامه می گرددید :

try:

    products = open("d:\\data2\\product.txt","w")

    products.write("Leyboard,202")

except:

    print("There is an Error")

finally:   

    products.close()

 

 

بکارگیری رهنمون with

هر منبع خارجی مانند فایل ، اتصال شبکه یا اتصال به پایگاه داده که تلاش برای بازکردن آن با استفاده از رهنمون with اداره شود با پایان یافتن بدنه رهنمون with  به صورت خودکار بسته خواهد شد. در مقایسه با رویکرد بکارگیری ساختار try با بهره گیری از رهنمون with می توانید کد تمیزتر و ایمن تری بنویسید. الگوی کلی نگارش و بکارگیری این رهنمون همانند زیر است :

 

with  expression  as  target_var:

            do_something

مثال :

with open("d:\\data\\product.txt","w") as products:

         products.write("Leyboard,202")

توجه کنید که کد بالا تنها بسته شدن فایل در صورت موفق بودن عملیات باز شدن فایل را تضمین می کند و هر خطایی که ممکن است در جریان تلاش برای باز کردن فایل رخ دهد را نمی تواند مدیریت کند و این گونه خطاها به ناگزیر باید با استفاده از ساختار try اداره شوند درمثال زیر برای اطمینان از بسته شدن فایل و اداره استثناهای رخ داده در دستورopen()  ترکیبی از دو رویکرد try و with بکار گرفته شده است:

مثال :

try :

     with open("d:\\data2\\product.txt","w") as products:

            products.write("Leyboard,202")

except FileNotFoundError as e:

     print(e)



[1] list

[2] dictionary

[3] tuple

[4] RAM

[5] Operating System (OS)

[6] Hard Disk

[7] CD , DVD

[8] Text

[9] Binary

[10] string

[11] encoding

[12] Binary

[13] File Object

[14] Parameter

[15] File Object

[16] character

[17] Byte

[18] End Of Line (EOL)

[19] Carriage Return Line Feed

 

[20] Line Feed

[21] File Object

[22] Buffer

نظرات 0 + ارسال نظر
برای نمایش آواتار خود در این وبلاگ در سایت Gravatar.com ثبت نام کنید. (راهنما)
ایمیل شما بعد از ثبت نمایش داده نخواهد شد