Энэ хичээл дээр бид хоёрдогч санах ой буюу Secondary Memory эсвэл файл-тай ажиллаж эхэлнэ. Цахилгааныг унтраасан үед хоёрдогч санах ой арилдаггүй. Эсвэл USB флаш дисĸний хувьд бидний программаас бичсэн өгөгдлийг системээс устгаж, өөр систем рүү зөөвөрлөх боломжтой.
Бид файлыг унших, файлруу бичихийг хүсвэл эхлээд файлыг нээх ёстой. Файлыг нээх нь таны үйлдлийн системтэй холбогдож, файл бүрийн өгөгдөл хаана хадгалагдаж байгааг мэддэг. Файлыг нээх үед та үйлдлийн системээс тухайн файлыг нэрээр нь олж, файл байгаа эсэхийг шалгахыг хүсч байна. Энэ жишээнд бид open() метод ашиглан mbox.txt файлыг нээж байгаа бөгөөд энэ файл нь таны Python-г эхлүүлж байгаа хавтсанд хадгалагдсан байх ёстой.
>>> fhand = open('mbox.txt')
>>> print(fhand)
<_io.TextIOWrapper name='mbox.txt' mode='r' encoding='cp1252'>
Хэрэв нээлт амжилттай болсон бол үйлдлийн систем бидэнд файлын заагч (handle) буцаана. file handle нь файлд агуулагдах бодит өгөгдөл биш, харин өгөгдлийг уншихад ашиглаж болох "заагч" юм. Хэрэв таны хүссэн файл оршин байгаа бөгөөд та тухайн файлыг унших зохих эрхтэй бол танд энэхүү заагчийг өгдөг
Хэрэв файл байхгүй бол нээх ажиллагаа амжилтгүй болох бөгөөд та файлын агуулгад хандах хандалтыг авахгүй.
>>> fhand = open('stuff.txt')
Traceback (most recent call last):
File "< stdin>", line 1, in < module>
FileNotFoundError: [Errno 2] No such file or directory: 'stuff.txt'
Энэ файл дотор цахим шуудангийн ирсэн, хариулсан огноо, хэн явуулсан, хэнрүү явуулсан, хэзээ явуулсан, явуулсан мейлийн гарчиг, теĸст агуулга гэх мэт дүүрэн өгөгдөл байгаа:
From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008
Return-Path: < postmaster@collab.sakaiproject.org>
Date: Sat, 5 Jan 2008 09:12:18 -0500
To: source@collab.sakaiproject.org
From: stephen.marquard@uct.ac.za
Subject: [sakai] svn commit: r39772 - content/branches/
Details: http://source.sakaiproject.org/viewsvn/?view=rev&rev=39772
...
Үүнийг бид уншиж, өөрчилж, өгөгдлийн бүтцийг анализ хийж үзэх болно.
Файлыг мөр болгон хуваахын тулд шинэ мөрийн тэмдэгт гэж нэрлэгддэг мөрийн төгсгөлийг илэрхийлэх \n тусгай тэмдэгт байдаг. Энэ тэмдэгт харагддаггүй ч мөрийн төгсгөл бүхэнд байдгаар төсөөлөх хэрэгтэй.
>>> print("Hello\nWorld")
Hello
World!
Мөн \n тусгай тэмдэгт нь тухайн мөрийнхээ 1 энгийн тэмдэгтийн зай эзэлдэн юм:
>>> stuff = 'X\nY'
>>> print(stuff)
X
Y
>>> len(stuff)
3
шинэ мөрийн \n тэмдэгт нь файл дахь тэмдэгтүүдийг мөрөнд хуваана.
file handle нь файлын өгөгдлийг агуулаагүй ч файлын мөр бүрийг уншиж, тоолохын тулд for loop ашиглахад маш хялбар байдаг:
fhand = open('mbox-short.txt')
count = 0
for line in fhand:
count = count + 1
print('Line Count:', count)
Хэрэв та үндсэн санах ойг хэт ачааллахааргүй харьцангуй жижиг файл гэдгийг мэдэж байгаа бол file handle дээрх унших аргыг ашиглан файлыг бүхэлд нь нэг мөр болгон уншиж болно.
>>> fhand = open('mbox-short.txt')
>>> inp = fhand.read()
>>> print(len(inp))
94626
>>> print(inp[:20])
From stephen.marquar
Энэ жишээнд mbox-short.txt файлын агуулгыг бүхэлд нь (бүгд 94,626 тэмдэгт) inp хувьсагч руу шууд хадгалж байна. Бид inp-д хадгалагдсан string өгөгдлийн эхний 20 тэмдэгтийг хэвлэхийн тулд string slice метод ашиглав.
Файлыг ийм байдлаар унших үед бүх мөр, шинэ мөрийн тэмдэгтүүд зэрэг бүх тэмдэгтүүд inp хувьсагчийн нэг том тэмдэгт болно. Унших үйлдэл бүр санах ойн нөөцийг шавхдаг тул read()-ийн гаралтыг хувьсагч болгон хадгалах нь зүйтэй. Тэгээгүй тохиолдолд бид өгөгдлийг барьж авч чадалгүй алдах болно:
>>> fhand = open('mbox-short.txt')
>>> print(len(fhand.read()))
94626
>>> print(len(fhand.read()))
0
Та файл доторх өгөгдлөөс тодорхой агуулга хайж байхдаа хэрэггүй мөрүүдийг алгасч, зөвхөн тодорхой нөхцөлийг хангасан мөрүүдийг түүж ашиглах нь зүйтэй. Бид энгийн хайлтын механизмыг бий болгохын тулд файлыг унших загварыг string методуудтай хослуулж болно.
Жишээлбэл, хэрэв бид файлыг уншиж, зөвхөн "From:" угтвараар эхэлсэн мөрүүдийг хэвлэхийг хүсвэл startswith гэсэн string аргыг ашиглан зөвхөн хүссэн угтвартай мөрүүдийг сонгож болно.
fhand = open('mbox-short.txt')
for line in fhand:
if line.startswith('From:'):
print(line)
Үр дүн:
From: stephen.marquard@uct.ac.za
From: louis@media.berkeley.edu
From: zqian@umich.edu
From: rjlowe@iupui.edu
...
Бидний хүсч байсан "From:" гэж эхэлсэн мөрүүд хэвлэгдэв, гэхдээ яагаад бид нэмэлт хоосон мөрүүдийг харж байна вэ? Энэ нь нөгөө үл үзэгдэх шинэ мөрийн \n тэмдэгттэй холбоотой юм.
Сүүлчийн тэмдэгтээс бусад бүх зүйлийг хэвлэхийн тулд бид line slice методыг ашиглаж болох боловч мөрийн баруун талын хоосон зайг дараах байдлаар арилгадаг rstrip методыг ашиглах нь илүү оновчтой арга юм:
fhand = open('mbox-short.txt')
for line in fhand:
line = line.rstrip()
if line.startswith('From:'):
print(line)
Одоо хоосон мөрүүд алга боллоо:
From: stephen.marquard@uct.ac.za
From: louis@media.berkeley.edu
From: zqian@umich.edu
From: rjlowe@iupui.edu
From: zqian@umich.edu
From: rjlowe@iupui.edu
From: cwen@iupui.edu
...
Бас нэг арга бол хэрэггүй мөрүүдийг алгасах загварыг дагаж loop-ыг дараах байдлаар зохион байгуулж болно:
fhand = open('mbox-short.txt')
for line in fhand:
line = line.rstrip()
# Skip 'uninteresting lines'
if not line.startswith('From:'):
continue
# Process our 'interesting' line
print(line)
Үр дүн яг адил байх болно.
Хайлтын мөр мөрний аль ч хэсэгт байгаа мөрүүдийг олох теĸст засварлагчийн хайлтыг дуурайлган хийхдээ бид find() методыг ашиглаж болно. Find нь теĸст дотор байгаа мөрийг хайж, хайж буй мөрийн байрлалыг буцаадаг, олдоогүй бол -1 гэсэн утгыг буцаадаг тул "@uct.ac.za" мөрийг агуулсан мөрүүдийг харуулахын тулд бид дараах loop бичиж болно:
hand = open('mbox-short.txt')
for line in fhand:
line = line.rstrip()
if line.find('@uct.ac.za') == -1:
continue
print(line)
'@uct.ac.za' биш бол алгас гэсэн логиĸ ашиглав. Тэгэхээр мөн бол хэвлэнэ гэсэн үг.
Бид өөр өөр файлтай ажиллах бүртээ Python ĸодоо засварлахыг үнэхээр хүсэхгүй байх нь мэдээж.
Python ĸодыг өөрчлөхгүйгээр өөр өөр файлууд дээр манай програмыг ашиглах боломжтой болгохын тулд хэрэглэгчээс програмыг ажиллуулах бүрт файлын нэрийн мөрийг оруулахыг хүсэх нь оновчтой байх болно.
Үүнийг input ашиглан хэрэглэгчээс файлын нэрийг уншиж авах замаар хялбархан хийж болно:
fname = input('Enter the file name: ')
fhand = open(fname)
count = 0
for line in fhand:
if line.startswith('Subject:'):
count = count + 1
print('There were', count, 'subject lines in', fname)
Үр дүн:
python search6.py
Enter the file name: mbox.txt
There were 1797 subject lines in mbox.txt
python search6.py
Enter the file name: mbox-short.txt
There were 27 subject lines in mbox-short.txt
Бид хэрэглэгчээс файлын нэрийг уншиж, түүнийг fname гэсэн хувьсагчид хадгалаад тэр файлыг нээдэг. Одоо бид програмаа өөр өөр файлуудад дахин дахин ажиллуулах боломжтой болж байна.
Хэрэв хэрэглэгч файлын нэр биш өөр зүйл бичвэл яах вэ? Мэдээж алдаа зааж программ ажиллахгүй болно. Тэгвэл try-except ашиглавал хэрэглэгчээс алдаатай мэдээлэл оруулах тохиолдлыг хянаж чаддаг болно:
жишээ нь:
fname = input('Enter the file name: ')
try:
fhand = open(fname)
except:
print('File cannot be opened:', fname)
exit()
count = 0
for line in fhand:
if line.startswith('Subject:'):
count = count + 1
print('There were', count, 'subject lines in', fname)
Файл бичихийн тулд та үүнийг хоёр дахь параметр болгон "w" горимтойгоор нээх ёстой:
fout = open('output.txt', 'w')
print(fout)
< _io.TextIOWrapper name='output.txt' mode='w' encoding='cp1252' >
Хэрэв файл аль хэдийн байгаа бол түүнийг бичих горимд нээх нь хуучин өгөгдлийг арилгаж, шинээр эхлэх тул болгоомжтой байгаарай! Хэрэв файл байхгүй бол шинээр үүсгэнэ.
file handler-ын объеĸтын write() метод нь өгөгдлийг файлд оруулж, бичсэн тэмдэгтүүдийн тоог буцаана.
>>> line1 = "This here's the wattle,\n"
>>> fout.write(line1)
24
Дахин хэлэхэд, файлын объеĸт хаана байгааг нь хянаж байдаг тул хэрэв та write() гэж дахин дуудвал энэ нь шинэ өгөгдлийг төгсгөлд нь нэмнэ.
Бид мөрийг дуусгахыг хүсвэл шинэ мөрийн тэмдэгтийг тодорхой оруулах замаар файл руу бичихдээ мөрийн төгсгөлийг удирдах ёстой. Хэвлэх мэдэгдэл нь шинэ мөрийг автоматаар нэмэх боловч write() метод нь шинэ мөрийг автоматаар нэмдэггүй.
>>> line2 = 'the emblem of our land.\n'
>>> fout.write(line2)
24
Бичиж дууссаны дараа та файлыг хаах хэрэгтэй бөгөөд энэ нь хамгийн сүүлийн бит өгөгдөл дисĸ рүү биечлэн бичигдсэн байх тул цахилгаан унтарвал алга болохгүй.
>>> fout.close()