خواندن خط به خط فایل در پایتون
# معرفی
یکی از متداول کارهایی که در زمان برنامه نویسی ممکن است با آن مواجه شوید، خواندن فایل است. کار با فایلها بسیار ساده است، فقط کافیست آن را باز کرده و محتویات آن را بخوانید. اما اگر فایل خیلی بزرگ باشد چه؟ مثلا چند گیگابایت. در این حالت دیگر نمیتوانید به راحتی فایل را باز کنید چون باعث اشغال مقدار زیادی ار حافظه شما خواهد شد. برای حل این مشکل باید فایل را به تکههای کوچکتر تقسیم کرده و به صورت تکه تکه با آن کار کنید. اندازه هر تکه بستگی به برنامه شما دارد اما مرسوم است که به شکل خط به خط اطلاعات را میخوانند.
در این مقاله روشهای متداولی که در پایتون برای تکه تکه کردن و خواندن فایلها وجود دارد را نشان خواهیم داد.
ویدیو مرتبط: ویدیو آموزش کار با فایل ها در پایتون
# خواندن فایل در پایتون
پایتون روشهای مختلفی برای خواندن فایل در خود دارد. متد داخلی open پایتون برای خواندن و نوشتن فایلها استفاده میشود. به شکل زیر میتوانید از آن استفاده کنید:
fp = open('path/to/file.txt', 'r')
همانطور که در کد بالا دیدید، متد open چند آرگومان میگیرد. آرگومان اول مسیر فایلی است که میخواهید از آن برای خواندن یا نوشتن استفاده کنید. آرگومان دوم حالت باز کردن فایل را مشخص میکند. فایلها را میتوانید با حالتهای مختلفی باز کرده و با آنها کار کنید:
- r - برای خواندن محتویات فایل
- w - برای نوشتن در فایل
- a - برای اضافه کردن به محتویات فایل
- rb - برای خواندن محتویات باینری از فایل
- wb - برای نوشتن محتویات باینری در فایل
بعد از اینکه کارتان با فایل تمام شد، باید فایل را ببندید که حافظه خالی شود. میتوانید از متد close برای اینکار استفاده کنید:
fp.close()
بستن فایلها کاری ضروری است اما در بسیاری مواقع فراموش میشود. یک روش بهتر برای باز کردن فایلها استفاده از کلمه کلیدی with است که یک context manager ایجاد میکند. با استفاده از with بستن فایل به طور اتوماتیک انجام میشود:
with open('path/to/file.txt') as fp:
# Do stuff with fp
روش دیگری که کمتر استفاده میشود، استفاده از بلوک try...finally است. در این روش هم مطمئن میشویم که بعد از اتمام کار، فایل را ببندیم:
try:
fp = open('path/to/file.txt')
# Do stuff with fp
finally:
fp.close()
هر دوی این روشها را میتوانید استفاده کنید اما پیشنهاد میشود از with استفاده کنید.
متد open یک آبجکت فایل را بعد از بازکردن فایل برمیگرداند. از این آبجکت میتوانید سه متد read, readline و readlines را استفاده کنید. متد read تمام محتویات فایل را یکجا میخواند. این متد برای فایلها کوچک مناسب است. متد readline فایل را به شکل خط به خط خوانده و برمیگرداند. متد readlines تمام خطوط فایل را خوانده و آنها را در قالب یک list برمیگرداند.
نکته: برای مثالهای این مقاله ما از کتاب "ایلیاد هومر" استفاده میکنیم. برای دانلود این کتاب میتوانید به وبسایت Gutenberg مراجعه کنید.
مقاله پیشنهادی: 8 روش برای بررسی وجود فایل در پایتون
# خواندن فایل خط به خط با readline در پایتون
متد readline برای خواندن یک خط استفاده میشود. در زمان استفاده از این متد باید یک متغیر شمارنده ایجاد کنید که شماره خط خوانده شده را یکی یکی اضافه کند:
filepath = 'Iliad.txt'
with open(filepath) as fp:
line = fp.readline()
cnt = 1
while line:
print("Line {}: {}".format(cnt, line.strip()))
line = fp.readline()
cnt += 1
کد بالا یک فایل باز کرده، آبجکت آن را در fp ذخیره کرده و خطوط فایل را یک به یک با متد readline در حلقه while میخواند. در آخر هر خط را چاپ میکند. بعد از اجرای کد بالا، نتیجهای مشابه این را میبینید:
...
Line 567: exceedingly trifling. We have no remaining inscription earlier than the
Line 568: fortieth Olympiad, and the early inscriptions are rude and unskilfully
Line 569: executed; nor can we even assure ourselves whether Archilochus, Simonides
Line 570: of Amorgus, Kallinus, Tyrtaeus, Xanthus, and the other early elegiac and
Line 571: lyric poets, committed their compositions to writing, or at what time the
Line 572: practice of doing so became familiar. The first positive ground which
Line 573: authorizes us to presume the existence of a manuscript of Homer, is in the
Line 574: famous ordinance of Solon, with regard to the rhapsodies at the
Line 575: Panathenaea: but for what length of time previously manuscripts had
Line 576: existed, we are unable to say.
...
این رویکرد ساده و صریح است و آنچنان پایتونی در نظر گرفته نمیشود. با متد readlines میتوانیم اینکار را بهتر انجام دهیم.
مقاله پیشنهادی: تبدیل انواع داده در پایتون
# خواندن فایل خط به خط با readlines در پایتون
متد readlines تمام خطوط فایل را خوانده و آنها را در یک لیست ذخیره میکند. سپس میتوانیم با متد enumerate در این خطوط چرخیده و شمارش هر خط را انجام دهیم:
file = open('Iliad.txt', 'r')
lines = file.readlines()
for index, line in enumerate(lines):
print("Line {}: {}".format(index, line.strip()))
file.close()
اگر کد بالا را اجرا کنید:
...
Line 160: INTRODUCTION.
Line 161:
Line 162:
Line 163: Scepticism is as much the result of knowledge, as knowledge is of
Line 164: scepticism. To be content with what we at present know, is, for the most
Line 165: part, to shut our ears against conviction; since, from the very gradual
Line 166: character of our education, we must continually forget, and emancipate
Line 167: ourselves from, knowledge previously acquired; we must set aside old
Line 168: notions and embrace fresh ones; and, as we learn, we must be daily
Line 169: unlearning something which it has cost us no small labour and anxiety to
Line 170: acquire.
...
این روش بهتر است. حالا دیگر لازم نیست هر بار متد readlines را صدا بزنیم. این روش سنتی خواندن فایلها است و روشهای مدرنتری برای اینکار وجود دارد.
مقاله پیشنهادی: 4 روش برای دانلود فایل با پایتون
# خواندن فایل خط به خط با حلقه for در پایتون
این روش بهترین است. آبجکت برگشتی قابل پیمایش است. نیازی نیست از متد readlines برای خواندن خطوط استفاده کنید، میتوانیم در خود آبجکت فایل پیمایش کنیم. با این روش به راحتی میتوانیم از enumerate و print هم استفاده کنیم.
این روش کوتاهترین و پایتونی ترین روش است:
with open('Iliad.txt') as f:
for index, line in enumerate(f):
print("Line {}: {}".format(index, line.strip()))
نتیجه کد بالا:
...
Line 277: Mentes, from Leucadia, the modern Santa Maura, who evinced a knowledge and
Line 278: intelligence rarely found in those times, persuaded Melesigenes to close
Line 279: his school, and accompany him on his travels. He promised not only to pay
Line 280: his expenses, but to furnish him with a further stipend, urging, that,
Line 281: "While he was yet young, it was fitting that he should see with his own
Line 282: eyes the countries and cities which might hereafter be the subjects of his
Line 283: discourses." Melesigenes consented, and set out with his patron,
Line 284: "examining all the curiosities of the countries they visited, and
...
در این روش ما از قابلیتهای داخلی پایتون برای خواندن فایل استفاده میکنیم.
مقاله پیشنهادی: آموزش دستور import در پایتون
# برنامههای خواندن فایل در پایتون
اکثر برنامههای NLP از فایلهای حجیم دیتا استفاده میکنند. اصلا عاقلانه نیست که این حجم از فایل را در حافظه باز کنید. اگر بخواهید شمارش کلمات را در یک فایل بررسی کنید میتوانید برنامه خودتان را بنویسید، هر چند که استفاده از پکیجهای خارجی مناسب تر است. در مثال پایین کدی نوشتهایم که یک فایل را لود میکند، کلمات را میشمارد و 10 کلمهای که بیشترین تکرار را داشته باشد، چاپ میکند:
import sys
import os
def main():
filepath = sys.argv[1]
if not os.path.isfile(filepath):
print("File path {} does not exist. Exiting...".format(filepath))
sys.exit()
bag_of_words = {}
with open(filepath) as fp:
for line in fp:
record_word_cnt(line.strip().split(' '), bag_of_words)
sorted_words = order_bag_of_words(bag_of_words, desc=True)
print("Most frequent 10 words {}".format(sorted_words[:10]))
def order_bag_of_words(bag_of_words, desc=False):
words = [(word, cnt) for word, cnt in bag_of_words.items()]
return sorted(words, key=lambda x: x[1], reverse=desc)
def record_word_cnt(words, bag_of_words):
for word in words:
if word != '':
if word.lower() in bag_of_words:
bag_of_words[word.lower()] += 1
else:
bag_of_words[word.lower()] = 1
if __name__ == '__main__':
main()
این کد از ماژول os استفاده میکند تا مطمئن شود فایل که قرار است خوانده شود، واقعا وجود دارد. اگر فایل وجود داشته باشد، خطوط را خط به خط خوانده و به فانکشن record_word_cnt ارسال میکند. در فانکشن bag_of_words کلمات را با فاصله از هم جدا کرده و وارد یک دیکشنری میکند. بعد از اینکه تمام خطوط فایل خوانده شدند، با فانکشن order_bag_of_words لیست کلمات را برمیگرداند که در آخر ما 10 کلمه با بیشترین تکرار را چاپ میکنیم.
حالا اگر کد بالا را اجرا کنید:
$ python app.py Iliad.txt
نتیجه به شکل زیر خواهد بود:
Most frequent 10 words [('the', 15633), ('and', 6959), ('of', 5237), ('to', 4449), ('his', 3440), ('in', 3158), ('with', 2445), ('a', 2297), ('he', 1635), ('from', 1418)]
# نتیجه گیری
در این مقاله بهترین روشهای خواندن خط به خط فایلها در پایتون را دیدید.