Урок 10 – Файловий Ввід та Вивід

Вступ

На останньому уроці ми з вами навчились імпортувати та використовувати код з інших модулів. На цьому ж уроці спробуємо трішки розібратися з роботою з файлами, як їх відкривати, записувати дані і навіть як зберігати та відновлювати цілі екземпляри (так – Пітонівські об’єкти) напряму у файли. Забули що означає термін Екземпляр? Тоді пропоную пригадати один з попередніх уроків про Класи у мові Python.

Відкривання Файлу

Для того, щоб відкрити файл, ми зазвичай користуємося вбудованою у мову Пітон функцією ‘open’. Дана функція отримує ряд аргументів, якими ми повідомляємо чи хочемо читати з файла, а чи можливо навпаки записати дані у нього, ну і звичайно передаємо шлях до самого файла. Отже, давайте на живому прикладі спробуємо відкрити файл для читання (у режимі read – ‘r’ ):

У вище наведеному прикладі функція ‘open’ повернула так званий дескриптор файлу, який ми потім пожемо прочитати, щоб отримати вміст нашого відкритого файлу. Метод read об’єкта відкритого файлу 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(), нам треба скористатися викликом:

Тепер коли ми знаємо базу: методи ‘read’ та ‘seek’, давайте розглянемо інші не менш корисні функцій роботи з файловим вводом та виводом у Пітоні.

Інші Функції Вводу та Виводу

Існує маса інших функцій для роботи з файлами. Ці функції мають багато застосувань, що дають нам змогу робити багато різних речей значно простіше. Давайте розглянемо з вами функції tell, readline, readlines, write та функцію close.

tell() – дана фукція повертає поточну позицію курсора у файлі. Вона не приймає жодних параметрів, просто викликаєте її з порожніми дужками і отримуєте число – позицію курсора. Дана функція є неймовірно корисною при читання з файлу.

readline() – вичитує дані з файлу починаючи з поточної позиції курсора і аж до кінця поточного рядка. Пам’ятайте, що кінець рядка – це не там де закінчується ваш екран монітора 😉 – рядок закінчується там, де натискаєте Enter (клавіша переводу на новий рядок), щоб створити новий рядок. Дана функція може бути корисною при вичитуванні файлів логування подій, або для того, щоб пробігатись по даних частинами, щоб потім їх по-трохи обробляти. readline також не приймає ніяких параметрів.

readlines() – ця функція дуже схожа на функцію readline(), проте вона вичитує усі рядочки до самого кінця файлу. А починає читати так само – від поточної позиції курсора у відкритому файлі. Дана функція повертає список із стрічок, де кожна стрічка містить рядок символів (тексту) із файлу. Наприклад, якщо б ми мали текстовий файл із наступним вмістом:

тоді наша функція readlines() повернула б наступні результати:

Ми отримали список стрічок. Зауважте символи ‘\n’ – це і є якраз ті сами переводи на наступний рядок, результат натискання клавіші Enter.

write() – ця функція записує дані у файл. Вона також поважає позицію курсора і починає писати у файл починаючи від нього, переписуючи наново (тобто перетираючи) усі наступні після курсора символи. Приблизно так само як в Microsoft Word, коли ви натискаєте режим заміни (Insert) і починаєте надписувати новий текст поверх існуючого. Дана функція приймає один параметр, який, власне, і є тими даними (стрічкою, текстом) для запису у файл. Приклад:

Зверніть увагу, що у прикладі зверху ми відкрили файл у режимі запису, передавши функції ‘open’ другим параметром символ ‘w’ (write).

А тепер спробуйте відкрити будь-який тестовий файл (або створити) і використовуючи вище наведені функції поекспериментуйте з даним файлом і його вмістом. Знаючи вище наведені функції, ми з вами можемо програмувати майже будь-який файловий редагувальний процес.

Пікли (Pickles), або як зберегти дані у файл

Pickles з англійської перекладається як закрутка, соління. Тобто щось законсервоване в банку, як наприклад мариновані огірки 🙂 Піклами в Пітоні називають збережені у файл екземпляри класів чи інші об’єкти. Об’єктами, як ми уже з вами знаємо, у мові Python є будь-яка сутність: змінна, інстанс класу, список, словник, функція, і т.д. Інші об’єкти також можуть бути “запіклені”, але є певні обмеження.

Після збереження в “пікл”, об’єкт пізніше може бути відновленим. Таким чином ми, можна сказати зберігаємо об’єкти.

Отож, як саме ми засолюємо (піклимо, зберігаємо) об’єкти? 🙂 А дуже просто. В Пітоні є модуль pickle, в якумо у свою чергу, знаходиться функція dump(), яка і робить усю важку роботу для нас. Досить просто? Давайте зараз з вами на прикладі спробуємо імпортувати функцію dump та скористатися нею, щоб зберегти об’єкт:

Спробуйте самі набрати вище наведений приклад у свому редакторі і запустити його. Після цього перевірте чи був створений новий файл myfile.db. Спробуйте відкрити і подивитися що всередині. А всередині буде те, що ми часто називаємо незрозумілими ієрогліфами. Це бінарний код, спеціальне представлення збережних пітоніських об’єктів, яке аж ніяк не призначене для людських очей 😉 Тому не переживайте, цей файл записала машина, тому машині її і вичитувати назад.

Отже, тепер давайте спробуємо з допомогою оберненої функції, під назвою load(), вичитати назад наш словник.

Виглядає круто, так? Але тут є одне обмеження, таким чином ми можемо зберегти лише один список (чи інший об’єкт) у один окремий файл. Але це обмеження можна обійти, наприклад, поклавши різні об’єкти для збереження у словник чи список, а вже той словник чи список – запіклити.

Загалом все по піклах.

Я неодноразово використовував пікли, щоб обійтись без повноцінної бази даних у невеличких проектах. Навіть Plone CMS (Zope фреймворк) використовують об’єктну базу даних – ZODB, яка використовує трохи розширений механізм Пітонівських піклів.

Думаю вам також може приходитись такий механіз для бази у одному з вашим майбутніх проектів.

На закінчення

Тепер ми з вами вміємо працювати з файлами, читати і записувати в них, а також рухатись посимвольно по файлах. Також знаємо, що таке пікли та де їх можна застосувати.

Гарна робота!

У наступному, і останньому уроці, ми з вами розглянемо тему Помилок. Як їх виловлювати, як правильно їх обробляти, і взагалі що таке помилка. Також як її правильно розуміти.

Виникли труднощі із запуском прикладів коду? Знайшли помилки? Маєте доповнення? Коментуйте у формі нижче! Я відповів на кожен коментар!

Коментарі:

  1. при запуску пітон файлу з кодом
    my=open(‘test.txt’,’r’)
    print my.seek(0)
    видає None
    з read все працювало!?

    Відповісти
    • cпробуйте після
      print my.seek(0)
      None
      знову команду
      print my.read()

  2. Скопіював Ваш приклад 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 -*- бо без неї файл не зберігався

  3. Привіт.
    Я не можу зрозуміти, що мені потрібно зробити спочатку. Відкрити текстовий файл через пітон? Відкрити пітонівський файл, як текстовий? Створити .ру який буде відкривати текстовий файл?
    І мені здається, що я чогось не дописую в коді (скоріше не розумію). Вирішив рухатись далі спробувати з піклами. Я передруковую код з сайту запускаю, а воно мені показує:
    ========================= RESTART: D:\Python\test.py =========================
    Це може бути пов’язане з тим що файл з піклом який я запускається не знаходиться в одній папці з програмою пітона?

    Відповісти
    • створюєш файл порожній, пишеш туди код на PYthon через текстовий редактор. уявлення не маю що таке RESTART

  4. При команді 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

    Відповісти
  5. Доброго дня! Не можу розібратися із відкриттям файлу, перепробував безліч варіантів і нічого не виходить, видає помилки
    >>> 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’)

  6. Всім привіт, маю таку помилку коли намагаюсь запіклити обєкт
    pickle.dump(mylist, myfile)
    TypeError: must be str, not bytes
    Підкажіть, будь ласка, що я зробив не так

    Відповісти
    • О так, іще. Знайшов дуже хороший онлайн ресурс який дозволяє писати і запускати код на різних мовах, може кому стане в пригоді (nitrous). І коли я запускаю код в ньому, все працює, чи я не так інсталював пайтон?

    • myfile у якому режимі відкриваєш? має бути в бінарному режимі, а не у текстовому

    • дам лише підказку. Почитай документація по функції dump і розберись якого типу аргументи вона приймає. Після цього перевір чи дійсно mylist i myfile підходять по типу.

  7. Код я прописав у файлі, потім через F5 запустив, працює, через командну стрічку, працює. Дальше в командну стрічку ввів myfile.seek(0) і викинуло оте вікно з російською мовою. Я не зовсім розумію де прописувати “seek”

    Відповісти
    • в командній стрічці немає змінної myfile. запуск файлу а потім командної стрічки – це дві абсолютно різні python сесії, том між ними зв’язку немає.

  8. Всім привіт. Просвітіть як користуватися ‘seek’. В пайтоні прописав:
    myfile = open(‘вказав шлях’, ‘r’)
    print myfile.read()
    викликав через командну стрічку, все працює; потім вводжу myfile.seek(0) викидає “myfile.seek” не является внутренней или внешней командой, исполняемой программой или пакетним файлом. Шо я зробив не так?

    Відповісти
    • “В пайноті прописав” – це мається на увазі прямо в інтерпретаторі чи у файлі? виглядає на те що myfile.seek використано в іншому місці ніж визначення змінної myfile

  9. Маю таблицю в бінарному коді. При відкриті текстовим редактором, наприклад gedit-ом, видно її як набір ієрогліфів. Як її можна прочитати Python щоб зберегти в людську txt таблицю? З чого починати?

    Відповісти
    • поняття немає що таке таблиця в бінарному коді і звідки ти її взяв 😉

  10. >>> tell()

    Traceback (most recent call last):
    File “”, line 1, in
    tell()
    NameError: name ‘tell’ is not defined

    Таку саму помилку видає і redline() i redlines()

    Відповісти
    • ці всі функції – це методи об’єкту файлового дескриптора. тобто, коли зроби open і присвоїв результат в змінну, тоді на даній змінній можна знайти оці всі методи

  11. виникла проблема з “розпіклити” файл.
    переглянувши створений *.db файл, побачив що він зовсім не “машинний”, а текстовий. тому при спробі відкрити цей файл видавало помилку. вирішення проблеми виявилось на диво банальним 🙂 в рядку:
    myfile = open(‘my_file.db’, ‘rb’) не потрібно вказувати що це бінарний режим, бо так не працює. зате працює у вигляді

    myfile = open(‘my_file.db’, ‘r’)

    Відповісти
    • досить дивно. опція ‘b’ зазвичай ніколи не заважає, навіть при відкритті текстових файлів

  12. 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

    Відповісти
    • давай повний трейсбек. програма працююча. і не можу зрозуміти яке відношення має та помилка до відкриття і вичитування файлу

  13. перший приклад коду по піклах:
    розкоментуй 17 стрічку
    #pickle.dump(mylist, myfile)
    другий приклад коду по піклах:
    6 стрічка, орфографія: Записаний файл

    Відповісти

Опублікувати коментар

Ваша e-mail адреса не оприлюднюватиметься.

Ви не робот? ;) *