Вступ
На останньому уроці ми з вами навчились імпортувати та використовувати код з інших модулів. На цьому ж уроці спробуємо трішки розібратися з роботою з файлами, як їх відкривати, записувати дані і навіть як зберігати та відновлювати цілі екземпляри (так – Пітонівські об’єкти) напряму у файли. Забули що означає термін Екземпляр? Тоді пропоную пригадати один з попередніх уроків про Класи у мові Python.
Відкривання Файлу
Для того, щоб відкрити файл, ми зазвичай користуємося вбудованою у мову Пітон функцією ‘open’. Дана функція отримує ряд аргументів, якими ми повідомляємо чи хочемо читати з файла, а чи можливо навпаки записати дані у нього, ну і звичайно передаємо шлях до самого файла. Отже, давайте на живому прикладі спробуємо відкрити файл для читання (у режимі read – ‘r’ ):
1 2 3 4 5 6 7 8 |
# відкриваємо файл my_file.txt, що знаходиться всередині папки # Documents; відкриваємо його для читання - другий аргумент є 'r' (read) myfile = open('/Documents/my_file.txt', 'r') # а тепер вичитуємо весь вміст файлу my_file.txt з допомогою метода # read вказівника файлу (так званого дескриптора - у нашому випадку myfile); # виводимо це все на екран print myfile.read() |
У вище наведеному прикладі функція ‘open’ повернула так званий дескриптор файлу, який ми потім пожемо прочитати, щоб отримати вміст нашого відкритого файлу. Метод read об’єкта відкритого файлу myfile вичитує і повертає весь вміст нашого файлу.
Шукай і знайдеш!
А тепер самі спробуйте у вашій програмі відкрити, вичитати і вивести на екран вміст будь-якого непорожнього текстового файлу на вашому диску. Як спробуєте, тоді лише продовжуйте далі даний урок… Я чекаю… 🙂
… Ну як, вдалось? Якщо ні, то які проблеми трапилися? Запостіть деталі в коментарі – допоможу розібратися.
А для тих, кому вдалося, пропоную ще раз запустити останній рядочок своєї програми. Там де є виклик метода ‘read’:
1 |
print myfile.read() |
Що отримали? Порожню стрічку. Це тому, що наш ‘курсор’ змінив свою позицію під час першого прочитання усього вмісту файлу (тоді коли ми вперше викликали метод ‘read’).
Що таке курсор? З курсором ви мабуть вже зустрічалися у своєму улюбленому редакторі коду. Це поточна ваша позиція у документі чи файлі. Це та позиція, звідки ви почнете вводити ваш текст. Також використовуючи клавіші стрілочок ви можете переміщувати курсор на нову позицію у файлі. Так от, такий самий принцип курсора при вичитуванні файла з допомогою коду на мові Пітон.
Курсор напряму повідомляє функції ‘read’ (та й в принципі усім іншим функцям вводу та виводу) звідки починати працювати з відкритим файлом. Курсор автоматично переміщається по файлу по мірі його прочитання. Таким чином при використанні функції ‘read’, ми вичитуємо повний вміст файлу, а отже отримуємо наш курсор на останній позиції у файлі – у самому кінці. Саме тому повторний виклик функції read повертає нам порожню стрічку. Функція починає вичитувати з позиції курсора, який на той момент є в кінці файлу, тому і вичитувати вже нічого.
Що ж робити? А є інший спосіб переміщати курсор у файлі – це використання методу ‘seek’ (з англ. ‘шукати’). Дана функція використовується у вигляді seek(offset, whence).
Параметр ‘whence’ є необов’язковим та визначає позицію звідки починати пошук у файлі. Якщо ‘whence’ є рівним нулю (0), тоді байти (символи) у файлі відраховуються від початку файла. Якщо 1 – тоді байти відраховуються від поточної позиції курсора. Якщо 2 – тоді байти відраховуються починаючи з кінця файла. Якщо аргумент ‘whence’ ми не передаємо, то його значення по замовчуванню є рівним 0.
Аргумент ‘offset’ описує як далеко від позиції ‘whence’ ми перемістимо курсор. Давайте пройдемось по кількох прикладах:
- myfile.seek(45, 0) – переміщаємо курсор на 45 байт (символів) відносно початку файлу
- myfile.seek(10, 1) – переміщаємо курсор на 10 байт (символів) відносно поточної позиції курсору
- myfile.seek(-77, 2) – переміщаємо курсор на 77 байт (символів) відносно кінця файлу (зауважте, що у цьому випадку ‘offset’ має бути від’ємним, позначаючи рух курсора справа – наліво)
А тепер спробуйте самі поекспериментувати з методом ‘seek’. Використовуйте даний метод, щоб переміщати курсор на будь-яку позицію у файлі. Одним із найпоширеніших його використань є переміщення курсора на початок файлу для повторного вичитування вмісту файлу.
Тобто, щоб повторно отримати вміст файлу, після першого виклику read(), нам треба скористатися викликом:
1 |
myfile.seek(0) |
Тепер коли ми знаємо базу: методи ‘read’ та ‘seek’, давайте розглянемо інші не менш корисні функцій роботи з файловим вводом та виводом у Пітоні.
Інші Функції Вводу та Виводу
Існує маса інших функцій для роботи з файлами. Ці функції мають багато застосувань, що дають нам змогу робити багато різних речей значно простіше. Давайте розглянемо з вами функції tell, readline, readlines, write та функцію close.
tell() – дана фукція повертає поточну позицію курсора у файлі. Вона не приймає жодних параметрів, просто викликаєте її з порожніми дужками і отримуєте число – позицію курсора. Дана функція є неймовірно корисною при читання з файлу.
readline() – вичитує дані з файлу починаючи з поточної позиції курсора і аж до кінця поточного рядка. Пам’ятайте, що кінець рядка – це не там де закінчується ваш екран монітора 😉 – рядок закінчується там, де натискаєте Enter (клавіша переводу на новий рядок), щоб створити новий рядок. Дана функція може бути корисною при вичитуванні файлів логування подій, або для того, щоб пробігатись по даних частинами, щоб потім їх по-трохи обробляти. readline також не приймає ніяких параметрів.
readlines() – ця функція дуже схожа на функцію readline(), проте вона вичитує усі рядочки до самого кінця файлу. А починає читати так само – від поточної позиції курсора у відкритому файлі. Дана функція повертає список із стрічок, де кожна стрічка містить рядок символів (тексту) із файлу. Наприклад, якщо б ми мали текстовий файл із наступним вмістом:
1 2 3 4 5 6 |
Hello World We are the Champions My name is Vova Last Line in My File |
тоді наша функція readlines() повернула б наступні результати:
1 2 3 |
>>> myfile = open('hello.txt', 'r') >>> myfile.readlines() ['\n', 'Hello World\n', '\n', 'We are the Champions\n', 'My name is Vova\n', '\n', 'Last Line in My File\n'] |
Ми отримали список стрічок. Зауважте символи ‘\n’ – це і є якраз ті сами переводи на наступний рядок, результат натискання клавіші Enter.
write() – ця функція записує дані у файл. Вона також поважає позицію курсора і починає писати у файл починаючи від нього, переписуючи наново (тобто перетираючи) усі наступні після курсора символи. Приблизно так само як в Microsoft Word, коли ви натискаєте режим заміни (Insert) і починаєте надписувати новий текст поверх існуючого. Дана функція приймає один параметр, який, власне, і є тими даними (стрічкою, текстом) для запису у файл. Приклад:
1 2 |
>>> myfile.open('to_write.txt', 'w') myfile.write('Hello World') |
Зверніть увагу, що у прикладі зверху ми відкрили файл у режимі запису, передавши функції ‘open’ другим параметром символ ‘w’ (write).
А тепер спробуйте відкрити будь-який тестовий файл (або створити) і використовуючи вище наведені функції поекспериментуйте з даним файлом і його вмістом. Знаючи вище наведені функції, ми з вами можемо програмувати майже будь-який файловий редагувальний процес.
Пікли (Pickles), або як зберегти дані у файл
Pickles з англійської перекладається як закрутка, соління. Тобто щось законсервоване в банку, як наприклад мариновані огірки 🙂 Піклами в Пітоні називають збережені у файл екземпляри класів чи інші об’єкти. Об’єктами, як ми уже з вами знаємо, у мові Python є будь-яка сутність: змінна, інстанс класу, список, словник, функція, і т.д. Інші об’єкти також можуть бути “запіклені”, але є певні обмеження.
Після збереження в “пікл”, об’єкт пізніше може бути відновленим. Таким чином ми, можна сказати зберігаємо об’єкти.
Отож, як саме ми засолюємо (піклимо, зберігаємо) об’єкти? 🙂 А дуже просто. В Пітоні є модуль pickle, в якумо у свою чергу, знаходиться функція dump(), яка і робить усю важку роботу для нас. Досить просто? Давайте зараз з вами на прикладі спробуємо імпортувати функцію dump та скористатися нею, щоб зберегти об’єкт:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# модуль testpickle.py # імпортуємо необхідні нам речі import pickle # давайте створимо словник, який потім і спробуємо запіклити mylist = ['hello', 3, 'ten', 10, 'nice day today'] # створимо новий файл, для цього відкриємо поки неіснуючий файл у режимі # для писання - 'w'; при відкриванні пітон створить нам # поки неіснуючий файл myfile = open('my_file.db', 'w') # а тепер збережемо наш словник використовуючи функцію dump # функція dump отримує два аргумента: дані, які треба зберігати; # а другим параметром - відкритий для читання файл - куди писати pickle.dump(mylist, myfile) # ну і на кінець не забуваймо закривати відкритий файл myfile.close() |
Спробуйте самі набрати вище наведений приклад у свому редакторі і запустити його. Після цього перевірте чи був створений новий файл myfile.db. Спробуйте відкрити і подивитися що всередині. А всередині буде те, що ми часто називаємо незрозумілими ієрогліфами. Це бінарний код, спеціальне представлення збережних пітоніських об’єктів, яке аж ніяк не призначене для людських очей 😉 Тому не переживайте, цей файл записала машина, тому машині її і вичитувати назад.
Отже, тепер давайте спробуємо з допомогою оберненої функції, під назвою load(), вичитати назад наш словник.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# модуль testunpickle.py # імпортуємо необхідні нам речі import pickle # відкриваємо наш попередньо записаний файл, але цього разу для читання # зауважте, що режим відкривання файла є 'rb': r - читати (read), b - бінарний режим, # тобто даємо знати пітону, що файл містить не текстові дані myfile = open('my_file.db', 'rb') # завантажуємо дані з файлу використовуючи функцію load модуля unpickle # Зверніть увагу: функція приймає відкритий файл, а не готові дані пікла mylist = pickle.load(myfile) # можемо закрити наш файл myfile.close() # роздрукуємо те, що в завантаженому списку, мають бути ті ж елементи, що ми # початково додали у наш список перед 'консервуванням' його у файл for item in mylist: print item |
Виглядає круто, так? Але тут є одне обмеження, таким чином ми можемо зберегти лише один список (чи інший об’єкт) у один окремий файл. Але це обмеження можна обійти, наприклад, поклавши різні об’єкти для збереження у словник чи список, а вже той словник чи список – запіклити.
Загалом все по піклах.
Я неодноразово використовував пікли, щоб обійтись без повноцінної бази даних у невеличких проектах. Навіть Plone CMS (Zope фреймворк) використовують об’єктну базу даних – ZODB, яка використовує трохи розширений механізм Пітонівських піклів.
Думаю вам також може приходитись такий механіз для бази у одному з вашим майбутніх проектів.
На закінчення
Тепер ми з вами вміємо працювати з файлами, читати і записувати в них, а також рухатись посимвольно по файлах. Також знаємо, що таке пікли та де їх можна застосувати.
Гарна робота!
У наступному, і останньому уроці, ми з вами розглянемо тему Помилок. Як їх виловлювати, як правильно їх обробляти, і взагалі що таке помилка. Також як її правильно розуміти.
Виникли труднощі із запуском прикладів коду? Знайшли помилки? Маєте доповнення? Коментуйте у формі нижче! Я відповів на кожен коментар!
Помилка:
# давайте створимо словник, який потім і спробуємо запіклити
mylist = [‘hello’, 3, ‘ten’, 10, ‘nice day today’]
Це не словник, а список.
при запуску пітон файлу з кодом
my=open(‘test.txt’,’r’)
print my.seek(0)
видає None
з read все працювало!?
cпробуйте після
print my.seek(0)
None
знову команду
print my.read()
Скопіював Ваш приклад testpickle.py (спочатку набрав сам, але теж не зміг запустити) і спробував запустити – видало:
Traceback (most recent call last):
File “C:\Users\user\Desktop\program\pickle.py”, line 5, in
import pickle
File “C:\Users\user\Desktop\program\pickle.py”, line 18, in
pickle.dump(mylist, myfile)
AttributeError: ‘module’ object has no attribute ‘dump’
До речі IDLE не хоче навіть зберігати файл без стрічки -*- coding: utf-8 -*-
(в мене Python 2.7)
не називай файл pickle.py він кофліктує із пітон вбудованим модулем.
перейменував файл однак результат той же…
Traceback (most recent call last):
File “C:/Users/user/Desktop/program/test1.py”, line 5, in
import pickle
File “C:/Users/user/Desktop/program\pickle.py”, line 18, in
pickle.dump(mylist, myfile)
AttributeError: ‘module’ object has no attribute ‘dump’
Файл повністю Ваш, єдине що я зробив – вставив стрічку -*- coding: utf-8 -*- бо без неї файл не зберігався
Привіт.
Я не можу зрозуміти, що мені потрібно зробити спочатку. Відкрити текстовий файл через пітон? Відкрити пітонівський файл, як текстовий? Створити .ру який буде відкривати текстовий файл?
І мені здається, що я чогось не дописую в коді (скоріше не розумію). Вирішив рухатись далі спробувати з піклами. Я передруковую код з сайту запускаю, а воно мені показує:
========================= RESTART: D:\Python\test.py =========================
Це може бути пов’язане з тим що файл з піклом який я запускається не знаходиться в одній папці з програмою пітона?
створюєш файл порожній, пишеш туди код на PYthon через текстовий редактор. уявлення не маю що таке RESTART
При команді mylist = pickle.load(my_file) видає наступне:
Traceback (most recent call last):
File “”, line 1, in
mylist = pickle.load(myfile)
File “C:\Python27\lib\pickle.py”, line 1378, in load
return Unpickler(file).load()
File “C:\Python27\lib\pickle.py”, line 858, in load
dispatch[key](self)
File “C:\Python27\lib\pickle.py”, line 966, in load_string
raise ValueError, “insecure string pickle”
ValueError: insecure string pickle
У другу спробу:
Traceback (most recent call last):
File “”, line 1, in
mylist = pickle.load(myfile)
File “C:\Python27\lib\pickle.py”, line 1378, in load
return Unpickler(file).load()
File “C:\Python27\lib\pickle.py”, line 858, in load
dispatch[key](self)
File “C:\Python27\lib\pickle.py”, line 1165, in load_put
self.memo[self.readline()[:-1]] = self.stack[-1]
IndexError: list index out of range
Доброго дня! Не можу розібратися із відкриттям файлу, перепробував безліч варіантів і нічого не виходить, видає помилки
>>> f=open(‘C\Python27\aaa.txt’, ‘r’)
Traceback (most recent call last):
File “”, line 1, in
f=open(‘C\Python27\aaa.txt’, ‘r’)
IOError: [Errno 2] No such file or directory: ‘C\\Python27\x07aa.txt’
>>> f=open(‘C:\Python27\aaa.txt’, ‘r’)
Traceback (most recent call last):
File “”, line 1, in
f=open(‘C:\Python27\aaa.txt’, ‘r’)
IOError: [Errno 22] invalid mode (‘r’) or filename: ‘C:\\Python27\x07aa.txt’
>>> f=open(‘Python27\aaa.txt’, ‘r’)
Traceback (most recent call last):
File “”, line 1, in
f=open(‘Python27\aaa.txt’, ‘r’)
IOError: [Errno 22] invalid mode (‘r’) or filename: ‘Python27\x07aa.txt’
В строці f=open(‘C:\Python27\aaa.txt’, ‘r’)
постав перед именем файла букву r,строка буде така:
f=open(r‘C:\Python27\aaa.txt’, ‘r’)
Всім привіт, маю таку помилку коли намагаюсь запіклити обєкт
pickle.dump(mylist, myfile)
TypeError: must be str, not bytes
Підкажіть, будь ласка, що я зробив не так
О так, іще. Знайшов дуже хороший онлайн ресурс який дозволяє писати і запускати код на різних мовах, може кому стане в пригоді (nitrous). І коли я запускаю код в ньому, все працює, чи я не так інсталював пайтон?
myfile у якому режимі відкриваєш? має бути в бінарному режимі, а не у текстовому
дам лише підказку. Почитай документація по функції dump і розберись якого типу аргументи вона приймає. Після цього перевір чи дійсно mylist i myfile підходять по типу.
Код я прописав у файлі, потім через F5 запустив, працює, через командну стрічку, працює. Дальше в командну стрічку ввів myfile.seek(0) і викинуло оте вікно з російською мовою. Я не зовсім розумію де прописувати “seek”
в командній стрічці немає змінної myfile. запуск файлу а потім командної стрічки – це дві абсолютно різні python сесії, том між ними зв’язку немає.
Всім привіт. Просвітіть як користуватися ‘seek’. В пайтоні прописав:
myfile = open(‘вказав шлях’, ‘r’)
print myfile.read()
викликав через командну стрічку, все працює; потім вводжу myfile.seek(0) викидає “myfile.seek” не является внутренней или внешней командой, исполняемой программой или пакетним файлом. Шо я зробив не так?
“В пайноті прописав” – це мається на увазі прямо в інтерпретаторі чи у файлі? виглядає на те що myfile.seek використано в іншому місці ніж визначення змінної myfile
Маю таблицю в бінарному коді. При відкриті текстовим редактором, наприклад gedit-ом, видно її як набір ієрогліфів. Як її можна прочитати Python щоб зберегти в людську txt таблицю? З чого починати?
поняття немає що таке таблиця в бінарному коді і звідки ти її взяв 😉
>>> tell()
Traceback (most recent call last):
File “”, line 1, in
tell()
NameError: name ‘tell’ is not defined
Таку саму помилку видає і redline() i redlines()
ці всі функції – це методи об’єкту файлового дескриптора. тобто, коли зроби open і присвоїв результат в змінну, тоді на даній змінній можна знайти оці всі методи
виникла проблема з “розпіклити” файл.
переглянувши створений *.db файл, побачив що він зовсім не “машинний”, а текстовий. тому при спробі відкрити цей файл видавало помилку. вирішення проблеми виявилось на диво банальним 🙂 в рядку:
myfile = open(‘my_file.db’, ‘rb’) не потрібно вказувати що це бінарний режим, бо так не працює. зате працює у вигляді
myfile = open(‘my_file.db’, ‘r’)
досить дивно. опція ‘b’ зазвичай ніколи не заважає, навіть при відкритті текстових файлів
myfile = open(‘/C:/Users/Andriy/Desktop/2.txt’,’r’) #/Documents/my_file.txt’, ‘r’)’
# а тепер вичитуємо весь вміст файлу my_file.txt з допомогою метода
# read вказівника файлу (так званого дескриптора – у нашому випадку myfile);
# виводимо це все на екран
print( myfile.read())
не працює,видає помилку:TypeError на строке 1: Can’t convert ‘int’ object to str implicitly
давай повний трейсбек. програма працююча. і не можу зрозуміти яке відношення має та помилка до відкриття і вичитування файлу
перший приклад коду по піклах:
розкоментуй 17 стрічку
#pickle.dump(mylist, myfile)
другий приклад коду по піклах:
6 стрічка, орфографія: Записаний файл
дякую, поправив