اغلب در مثالهای برنامهنویسی پایتون، برای ذخیرهی اطلاعات از متغیرها، لیستها، دیکشنری و… استفاده میشود، اما در واقعیت این اطلاعات برای استفادهی مجدد، باید در فایلها ذخیره شوند. به همین جهت، یادگیری کار با فایلها در پایتون و خواندن و نوشتن اطلاعات روی فایل، از اهمیت بالایی برخوردار است. در این مقاله، میخواهیم مثالی از کار با فایلها در پایتون بیاوریم. پس در ادامه با ما همراه شوید.
قصد داریم برنامهای نوشته که از داخل یک فایل CSV، اطلاعات چند دانشجو که شامل نام و نمرات آزمونهای آنها است را خوانده و در فایل CSV دیگری، نام و معدل نمرات آنها را ذخیره کند.
اطلاعات ورودی ما در یک فایل با فرمت csv ذخیره شده است. فایل csv یا Comma Separeted Values به معنای «مقادیر جدا شده با ویرگول» است. از این نوع فایل برای جابجایی دادهها و اطلاعات بین نرمافزارهای مختلف استفاده میشود. قالب csv، رایجترین فرمت وارد کردن و صادر کردن برای صفحات گسترده و پایگاه داده است.
در این نوع فایل دادهها در هر خط به وسیلهی ویرگول از هم جداسازی و محدودسازی میشوند. برای کسب اطلاعات بیشتر در این مورد Comma-separated values را مطالعه کنید.
برای نوشتن این برنامه ابتدا یک فایل csv با نامی دلخواه ذخیره میکنیم. سپس مقادیر زیر را در آن ذخیره میکنیم.
ali, 16, 17, 14, 19, 16
hamid, 13, 15 , 20 , 6, 17
jafar, 18, 12, 16 , 8 , 6 , 15
zahra, 17, 14 , 20, 19, 18 ,16
reza, 14, 20 , 5, 8 , 16
negar, 19, 18, 16 ,17, 12
maryam, 11, 18 , 16 , 9, 16
اکنون مقدمات لازم برای نوشتن برنامه را در اختیار داریم و میتوانیم به سراغ کدنویسی برنامه برویم.
قبل از هر چیز لازم است ابتدا کتابخانههایی که نیاز داریم را با دستور import در ابتدای کد وارد کنیم. برای این برنامه ما به کتابخانهای برای خواندن و نوشتن فایلهای csv نیاز داریم، که میتوانیم از کتابخانهی csv استفاده کنیم.
برای گرفتن معدل نمرات نیز ترجیح میدهیم از متد mean استفاده کنیم، که این متد در چند کتابخانه مختلف از جمله کتابخانههای statistics و math تعریف شده است. از آنجایی که اینها کتابخانههای بزرگ و پر حجمی هستند و وارد کردن کامل آنها داخل کد، باعث کندی کد خواهد شد، لذا ما فقط متد mean را وارد میکنیم. به این صورت:
import csv
from statistics import mean
…
اکنون باید در برنامه، فایل خود را باز کنیم که برای خواندن و نوشتن در فایل از تابع open() استفاده میکنیم. برای آن که کد ما از نحو نگارشی و مدیریت استثناء (Exception handling) بهتری برخوردار شود، از دستور with در کنار تابع open() استفاده میکنیم. ضمن اینکه در این شیوه، فایل پس از اتمام کار به صورت خودکار بسته میشود. روش باز کردن فایل به این صورت است:
import csv
from statistics import mean
with open('grade.csv', 'r') as csvfile:
…
چون آدرسدهی دایرکتوری در ویندوز و لینوکس متفاوت است، لذا در قطعه کد بالا، در قسمتی که نام فایل csv را نوشتیم (‘grade.csv’)، باید با توجه به سیستمعامل رایانهی خود آدرس محلی که فایل csv را ذخیره کردهاید را به صورت کامل اضافه کنید.
همان گونه که میبینید، در تابع open بعد از آدرس فایل، آرگومان دیگری که حرف r است، نوشته شده است. این همان حالتی است که مشخص میکند فایل باید خوانده یا نوشته شود. گزینههای مختلفی برای این منظور وجود دارد ولی پرکاربردترین آنها موارد زیر است:
بعد از باز کردن فایل، باید با کمک کتابخانهی csv آن را بخوانیم. به این صورت:
…
with open(grade.csv', 'r') as csvfile:
reader = csv.reader(csvfile) #نام به دلخواه است و هر نام دیگری میتوانید تعیین کنید
…
اکنون تمامی محتویات فایل ما، در reader وجود دارد که برای مشاهدهی آنها باید از حلقهی تکرار for استفاده کنیم. به این صورت:
…
with open('grade.csv', 'r') as csvfile:
reader = csv.reader(csvfile)
for row in reader:
print( row(
…
اگر در حلقهی تکرار از دستور پرینت استفاده کنیم، تمامی خطوط فایل csv چاپ میشود. اما نیازی به چاپ کردن نداریم و فقط باید معدل نمرات هر شخص را بگیریم. برای این کار ابتدا نام شخص را جدا کرده و سپس نمرات او را به اعشار تبدیل کرده و داخل لیستی اضافه میکنیم. به این صورت:
…
reader = csv.reader(csvfile)
for row in reader:
name = row[0]
grade_mean = []
for grade in row[1:]:
grade_mean.append(float(grade))
..
در پایتون این امکان وجود دارد که چند خط از کد بالا را در یک خط خلاصه کنیم. این قدرت پایتون را نشان میدهد. به این صورت:
…
reader = csv.reader(csvfile)
for row in reader:
name = row[0]
grade_mean = (float(grade) for grade in row[1:])
…
در اینجا نام شخص و لیست نمرات او جدا سازی شد و اکنون فقط کافی است با استفاده از متد mean معدل آن را بگیریم.
برای آن که اطلاعات به دست آورده خود را بعد در فایل ذخیره کنیم، لازم است ابتدا آنها را در لیست یا دیکشنری ذخیره کنیم. پس بعد از قسمتی که reader را تعریف کردیم یک لیست تعریف میکنیم و در پایان حلقهی for مقادیر را به لیست اضافه میکنیم. به این صورت:
…
with open('grade.csv', 'r') as csvfile:
reader = csv.reader(csvfile)
list_grade = []
for row in reader:
name = row[0]
grade_mean = (float(grade) for grade in row[1:])
list_grade.append([row[0], mean(grade_mean)])
…
قسمتی که مربوط به خواندن فایل و گرفتن معدل میشد، تکمیل شد اکنون نوبت به ایجاد فایل جدید و نوشتن نام و معدل دانشجوها در آن میرسد. برای این کار نیز از with open استفاده میکنیم اما حالت آن را “w” انتخاب میکنیم. به این صورت:
…
with open('grade.csv', 'r') as csvfile:
reader = csv.reader(csvfile)
list_grade = []
for row in reader:
name = row[0]
grade_mean = (float(grade) for grade in row[1:])
list_grade.append([name, mean(grade_mean)])
with open('mean.csv', 'w', newline='') as outfile:
...
نکته 1: تابع open دوم که برای نوشتن استفاده میشود باید داخل تابع open اول نوشته شود.
نکته 2: آرگومان سومی که داخل تابع open نوشته شده است (newline=”) باعث میشود خطوط اضافه داخل فایل نوشته نشود.
فایل دوم ما نیز باز شده و آماده برای نوشتن اطلاعات است. اکنون باید آن را به وسیلهی کتابخانهی csv فراخوانی و اطلاعات لیست خود را روی آن بنویسیم. برای این منظور از دستور زیر استفاده میکنیم.
…
with open('mean.csv', 'w', newline='') as outfile:
writer = csv.writer(outfile)
…
در قدم آخر، با یک حلقهی تکرار for لیستی که اطلاعات را روی آن ذخیره کردیم را پیمایش کرده و خط به خط روی فایل جدید مینویسیم. به این صورت:
…
with open('mean.csv', 'w', newline='') as outfile:
writer = csv.writer(outfile)
for item in list_grade:
writer.writerow(item)
اکنون کدنویسی برنامهی ما به پایان رسید و موفق شدیم اطلاعات یک فایل را خوانده و روی فایلی دیگر، اطلاعاتی جدیدتر بنویسیم. کد کامل و یک جای ما به صورت زیر است:
import csv
from statistics import mean
with open('grade.csv', 'r') as csvfile:
reader = csv.reader(csvfile)
list_grade = []
for row in reader:
name = row[0]
grade_mean = (float(grade) for grade in row[1:])
list_grade.append([name, mean(grade_mean)])
with open('mean.csv', 'w', newline='') as outfile:
writer = csv.writer(outfile)
for item in list_grade:
writer.writerow(item)
در کدی که در بالا نوشتیم، بعضی موارد میتواند بهبود یافته و از حجم کد کاسته شود و هم کد ما بهینهتر شود. ما در ادامه سعی خواهیم کرد که کد خود را بهبود ببخشیم.
در این قسمت، ما تابع open دوم را دقیقا بعد از reader مینویسیم. به این صورت:
import csv
from statistics import mean
with open('grade.csv', 'r') as csvfile:
reader = csv.reader(csvfile)
with open('mean.csv', 'w', newline='') as outfile:
writer = csv.writer(outfile)
…
حال عملیاتی که در بالا در open اول نوشتیم را در اینجا در تابع open دوم مینویسیم. و در اینجا لیست list_grade را حذف میکنیم. به این صورت:
…
with open('grade.csv', 'r') as csvfile:
reader = csv.reader(csvfile)
with open('mean.csv', 'w', newline='') as outfile:
writer = csv.writer(outfile)
for row in reader:
name = row[0]
grade_mean = (float(grade) for grade in row[1:])
…
در ادامه بدون هیچ واسطهای، اطلاعات را مستقیم روی فایل دوم ذخیره میکنیم. به این صورت:
…
with open('mean.csv', 'w', newline='') as outfile:
writer = csv.writer(outfile)
for row in reader:
name = row[0]
rade_mean = (float(grade) for grade in row[1:])
writer.writerow([name, mean(grade_mean)])
کد ما کوتاهتر و بهینهتر شد اما هنوز میتوانیم متغیر name را نیز حذف کرده و در هنگام نوشتن روی فایل از row[0] استفاده کنیم. به این صورت:
…
with open('mean.csv', 'w', newline='') as outfile:
writer = csv.writer(outfile)
for row in reader:
grade_mean = (float(grade) for grade in row[1:])
writer.writerow([row[0], mean(grade_mean)])
ما با اندکی ظرافت و خلاقیت، کد خود را بهینه و خلاصهتر کردیم. همیشه کدهای بهینه شده از سرعت و خوانایی بالاتری برخوردار است. کد کامل شدهی ما به صورت زیر است:
import csv
from statistics import mean
with open('grade.csv', 'r') as csvfile:
reader = csv.reader(csvfile)
with open('mean.csv', 'w', newline='') as outfile:
writer = csv.writer(outfile)
for row in reader:
grade_mean = (float(grade) for grade in row[1:])
writer.writerow([row[0], mean(grade_mean)])
شما میتوانید هر دو کد را با هم بررسی کرده و تفاوتها و شباهتهای آنها را مشاهده کنید و به طور قطع متوجه خواهید شد که کد دوم بسیار خواناتر از کد اول است، هر چند که کار هر دو کد یکی است.
یکی از مشکلاتی که ممکن است هنگام کار با فایلها در پایتون پیش آید و باعث ایجاد خطا گردد، وجود داشتن حروف و کاراکتر فارسی در فایلها است. اگر به چنین مشکلی برخورد کردید، فقط کافیست آرگومان “encoding=utf-8” را در داخل تابع open اضافه کنید. با این کار، پایتون با یونیکد UTF8 ، کاراکترهای فارسی را شناخته و از بروز خطای احتمالی جلوگیری میکند. به این صورت:
...
with open('grade.csv', 'r', encoding='utf-8') as csvfile:
reader = csv.reader(csvfile)
with open('mean.csv', 'w', encoding='utf-8', newline='') as outfile:
writer = csv.writer(outfile)
...
فایلها برای ذخیره اطلاعات در برنامهنویسی بسیار کاربردی است. برای آن که بتوانیم اطلاعات خود را در برنامههای دیگر و نیز در دفعات دیگر استفاده کنیم، ملزم به ذخیره در فایل هستیم. ما در مقالهی کار با فایلها در پایتون، برنامهای نوشتیم که از یک فایل نمرات یک دانشجو را خوانده و پس از گرفتن معدل آنها، در فایلی ذخیره کردیم. خواندن و نوشتن روی فایل در پایتون کار جذاب و با اهمیتی است که هر برنامهنویس پایتون، باید آن را بیاموزد.
در کار با فایل در پایتون برنامههای کاربردیتر و بهتری نیز میتوان نوشت. اگر از علاقهمندان به برنامهنویسی پایتون هستید، میتوانید به عنوان تمرین، برنامه خواندن و نوشتن فایل csv در پایتون را به روشهایی دیگر بنویسید.
اگر قصد دارید در مدت زمان کوتاهی برنامه نویسی را فرابگیرید، دورههای متخصص سون لرن در این مسیر پر فراز و نشیب همراه شما خواهند بود.
اگر به یادگیری بیشتر در زمینهی برنامه نویسی پایتون علاقه داری، یادگیری زبان پایتون بسیار ساده است. و با شرکت در دورهی آموزش پایتون توسعه وب در آینده میتونی اپلیکیشن موبایل و دسکتاپ بسازی و وارد حوزهی هوش مصنوعی هم شوی.
من چطوری اینارو تبدیل به floatکنم هرچی تو سایت ها میگردم جواب درستی نمیگیرم!
یکی از راحتترین کارها اینه که قبل از ترین یک دیتافریم بسازید و اطلاعات رو توش کپی کنید با این تفاوت که هنگام کپی نوع ستون رو به فلوت تبدیل کنید.
بعد دیتا فریم جدید رو ترین کنید.