понедельник, 7 декабря 2015 г.

Тип "файл" в Python; Методы взаимодействия с объектом файла

Файлы



Что такое файлы? Если коротко, файлы - именованные области памяти вашего жесткого диска, флешки и Т.Д. Мы встречаем 2 основных типа файлов - это бинарные файлы и текстовые.
Бинарные файлы, хранят в себе некие данные в двоичном формате и не предназначены для чтения текстовыми редакторами. Текстовые файлы хранят в себе текст, Т.Е. Набор символов. Естественно, что это могут быть какие-то служебные файлы, которые будут хранить в себе зашифрованные текстовые данные. Вы сможете открыть такие файлы текстовым редактором, но кроме умляутов, там ничего не будет. Для начала, мы будем рассматривать работу с текстовыми файлами. Что нам даст возможность работать с файлами? Самое главное, мы сможем брать какую-то сохраненную информацию с файлов и работать с ней в Python. Естественно, мы сможем записывать результаты работы нашей программы в файл. Вы обратили внимание, что все данные которые мы вводим наши приложения на Python, исчезают после перезагрузки нашего приложения, Т.К. Все данные, записываются в переменные, которые реально ведут на области оперативной памяти, где временно сохраняются наши данные. А сохраняются они до тех пор, пока на них есть какие-то ссылки, Т.Е. Переменные, которые ссылаются на эти данные. Как только мы выгружаем наше приложение, все ссылки исчезают и данные удаляются с нашей оперативной памяти. Файлы позволят сохранить необходимые данные и, при необходимости, загрузить их в наше приложение из файла. Посути, мы рассматриваем текстовый файл, как простейшую, незащищенную базу данных.


Открытие и закрытие файла в Python



Файл в Python - это еще один тип данных. Такой же объект, как и строка, список, словарь... Также имеет свои методы для взаимодействия. Чтобы иметь возможность работать с файлом, нам для начала нужно создать его объект. Выражаясь проще, нам необходимо открыть уже существующий файл, или открыть несуществующий файл, что приведет к его созданию. Для открытия файла, существует встроенная функция open(). Эта функция создает объект файла также, как создаются объекты при помощи функций int(), str(), list()... С этим объектом, мы и будем работать.

Синтаксис функции open():

Переменная_в_которую_заносится_объект = open(ur'путь_к_файлу', 'Модификатор_открытия')

Про переменную, я надеюсь, объяснять уже нет необходимости.

Путь к файлу указывается штатно 'c:\folder\file.txt'. Модификатор "u" перед путем файла, указывает на то, что путь нужно рассматривать в юникоде. Модификатор "r" перед путем, говорит о том, что это путь. Последнее утверждение не совсем правда, насамом деле, "r", экранирует нашу косую черту \. Совсем непонятно? Представте, что у вас в строке был бы путь скажем: 'c:\newfolder'. А теперь вспомним, что делает спец(эскейп) символ "\n". Он говорит строке о символе новой строки. Чтобы Python Не воспринял наш "\n" за символ новой строки, мы ставим перед строкой модификатор "r". Если не устанавливать этот модификатор, нам нужно писать двойные бекслеши \\, чтобы первая обратная косая черта, экранировала вторую, но про эскейп символы и экранизацию оных, мы будем говорить далее.

Модификатор открытия говорит нам о том, в каком режиме открывать файл. Файл может быть открыт для чтения, записи, чтения и записи одновременно, как текстовый, как бинарный. Указать вариант открытия, помогают следующие модификаторы:

r - Открывает файл только для чтения. Указатель стоит в начале файла.

rb - Открывает файл для чтения в двоичном формате. Указатель стоит в начале файла.

r+ - Открывает файл для чтения и записи. Указатель стоит в начале файла.

rb+ - Открывает файл для чтения и записи в двоичном формате. Указатель стоит в начале файла.

w - Открывает файл только для записи. Указатель стоит в начале файла. Создает файл с именем имя_файла, если такового не существует.

wb - Открывает файл для записи в двоичном формате. Указатель стоит в начале файла. Создает файл с именем имя_файла, если такового не существует.

w+ - Открывает файл для чтения и записи. Указатель стоит в начале файла. Создает файл с именем имя_файла, если такового не существует.

wb+ - Открывает файл для чтения и записи в двоичном формате. Указатель стоит в начале файла. Создает файл с именем имя_файла, если такового не существует.

a - Открывает файл для добавления информации в файл. Указатель стоит в конце файла. Создает файл с именем имя_файла, если такового не существует.

ab - Открывает файл для добавления в двоичном формате. Указатель стоит в конце файла. Создает файл с именем имя_файла, если такового не существует.

a+ - Открывает файл для добавления и чтения. Указатель стоит в конце файла. Создает файл с именем имя_файла, если такового не существует.

ab+ - Открывает файл для добавления и чтения в двоичном формате. Указатель стоит в конце файла. Создает файл с именем имя_файла, если такового не существует.


По умолчанию, если не указать модификатор, файл будет открыт в режиме чтения 'r'.


Информация о Файле



После открытия файла, мы можем узнать про него следующую информацию:

file.closed - Возвращает True если файл был закрыт.

file.mode - Возвращает режим доступа, с которым был открыт файл.

file.name - Возвращает имя файла.


Где "file" - это объект(переменная со ссылкой на объект) файла. Кпримеру:

>>> f = open(ur'd:\dev\myfile.txt', 'w') #Открыл файл для записи

>>> f.name

u'd:\\dev\\myfile.txt'

>>> print f.name

d:\dev\myfile.txt

>>> f.closed

False

>>> f.mode

'w'

>>> f.close()

>>> f.closed

True

>>>



Закрытие файла в Python



Метод файлового объекта close() автоматически закрывает файл, при этом теряется любая несохраненная информация. Работать с файлом (читать, записывать) после этого нельзя.

Python автоматически закрывает файл если файловый объект к которому он привязан присваивается другому файлу. Однако, хорошей практикой будет вручную закрывать файл командой close(). До закрытия файла, вы не сможете увидеть в нем изменения, которые были внесены во время работы с ним в Python.

Если у вас есть необходимость сохранить изменения в файл, но не закрывать его при этом, мы используем метод flush(). Этот метод сохранит все изменения в файл без необходимости его закрывать методом close().


Методы работы с файлом



Рассмотрим часто используемые методы для работы с файловым объектом. Далее поговорим про каждый из них более детально.

write() - позволяет записать в файл строку. Этот метод не вставляет "\n" и не создает новую строку после своего применения.

writelines() - позволяет записать в файл строку, список, кортеж. Элементы будут записаны в одну строку и метод не создает новую строку после своего применения.

read() - прочтет весь файл и вернет его в виде строки с разделением строк при помощи "\n".

readlines() - прочтет весь файл и вернет его в виде списка строк.

readline() - Будет возвращать нам по одной строке за одно применение, начиная со своего местоположения.

tell() - сообщает позицию указателя файла. (на каком символе, находится указатель.

seek() - устанавливает указатель на номер символа. "0" - начало файла.

close() - закрывает файл и записывает изменения.

flush() - записывает изменения в файл, не закрывая его.



Запись в файл



Договоримся, что мои файлы будут лежать по пути "d:\dev". На диске "d" в папке "dev". Вы можете размещать файлы там, где вам будет удобно.

Для начала откроем файл для записи с именем "myfile.txt".

>>> f = open(ur'd:\dev\myfile.txt', 'w')

>>>


Теперь рассмотрим 2 метода, которые позволяют записывать что-то в файл. Метод write(), позволит записать нам в файл строку. Нужно не забывать про кодировки. Для того, чтобы записать в файл текст с кодировкой utf-8, эта строка должна находиться в данной кодировке или вы должны применять метод encode(), для юникодового литерала, при записи строки в файл.

>>> a = u'Начало файла'.encode('utf-8')

>>> f.write(a)

>>> f.write('\n') #для создания новой строки

>>> f.write(u'Вторая строка файла\n'.encode('utf-8'))

>>> f.flush() #сбросили изменения в файл

>>>


Теперь вы можете открыть файл в текстовом редакторе. Там должно быть три строки:

Начало файла

Вторая строка файла

И пустая строка.

Далее посмотрим на метод writelines(). В него мы можем передать список элементов, которые будут записаны в одну строку без пробелов.

>>> a = ["Hello", "dear", "123"]

>>> a

['Hello', 'dear', '123']

>>> f.writelines(a)

>>> f.write('\n')

>>> f.flush()

>>>


Если вы откроете ваш файл текстовым редактором, увидете, как в конце, добавилась строка:

Hellodear123



В метод writelines(), мы можем передавать строку, список, кортеж или все, что возвращает упорядоченные списки элементов.

Внимание! То, что я не кодировал данные в utf-8 при демонстрации writelines() неправильно. Мы всеравно должны были записывать корректно закодированный текст. Но ведь все отображалось правильно? Да, вспоминаем, что английские символы, практически всегда отображаются корректно, а вы попробуйте записать в файл просто слово "привет", без игры с юникодом и кодировками, затем откройте файл и посмотрите на умляуты.

Для корректности, после всех экспериментов, закройте ваш файл методом close().


Чтение из файла(/h3)

Теперь посмотрим на то, как мы можем читать информацию из файла. Для чтения, нам послужит файл, который мы создали, когда рассматривали методы записи данных в файл.

И так, открываем файл для чтения, помним, что по умолчанию, без модификатора, файл открывается для чтения.

>>> f = open(ur'd:\dev\myfile.txt')

>>>


Начнем с метода read(), который вернет нам все содержимое файла в виде строки.

>>> text = f.read()

>>> text

'\xd0\x9d\xd0\xb0\xd1\x87\xd0\xb0\xd0\xbb\xd0\xbe \xd1\x84\xd0\xb0\xd0\xb9\xd0\x

bb\xd0\xb0\n\xd0\x92\xd1\x82\xd0\xbe\xd1\x80\xd0\xb0\xd1\x8f \xd1\x81\xd1\x82\xd

1\x80\xd0\xbe\xd0\xba\xd0\xb0 \xd1\x84\xd0\xb0\xd0\xb9\xd0\xbb\xd0\xb0\nHellodea

r123\n'

# Текст находится в кодировке utf-8

>>> print text

¦Э¦-TЗ¦-¦¬¦- TД¦-¦¦¦¬¦-

¦ТTВ¦-TА¦-TП TБTВTА¦-¦¦¦- TД¦-¦¦¦¬¦-

Hellodear123

# И опять таки, текст находится в кодировке utf-8

>>> print text.decode('utf-8')

Начало файла

Вторая строка файла

Hellodear123

# А вот так правильно, мы декодировали utf-8 в юникод



>>>


Тут мы видем еще один пример, как важно не забывать про кодировки.


Указатель файла



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

>>> lines = f.read()

>>> lines

''

>>>


Что произошло, почему нам вернулась пустая строка? Есть такое понятие, как указатель файла, когда мы открыли файл для чтения, указатель стоял на нулевом символе, Т.Е. на первом символе файла и, когда мы применили метод read(), Он пробежался до конца файла и остался там. Чтобы узнать позицию указателя, мы применим метод tell(), а для того, чтобы вернуть его обратно на начало файла, метод seek() с аргументом 0.

>>> f.tell()

77L

>>> f.seek(0)

>>> f.tell()

0L

>>> lines = f.read().decode('utf-8')

>>> print lines

Начало файла

Вторая строка файла

Hellodear123



>>>


Как видите, я вернул указатель на первый символ файла и опять смог получить его содержимое. Также вы могли заметить, что на этот раз, я просто декодировал utf-8 в юникод на лету. Тут все работает также, как и везде.

Что возвращает нам метод read()? Строку! А значит мы можем тутже применить строчный метод decode() к возвращаемому объекту.

Мы можем установить указатель на тот символ, с которого хотим начать чтение нашего файла.


Следующий метод, который позволяет получать содержимое файла - readlines(). Он возвращает список строк файла.

>>> lines = f.readlines()

>>> type(lines)



>>> len(lines)

3

>>> lines

['\xd0\x9d\xd0\xb0\xd1\x87\xd0\xb0\xd0\xbb\xd0\xbe \xd1\x84\xd0\xb0\xd0\xb9\xd0\

xbb\xd0\xb0\n', '\xd0\x92\xd1\x82\xd0\xbe\xd1\x80\xd0\xb0\xd1\x8f \xd1\x81\xd1\x

82\xd1\x80\xd0\xbe\xd0\xba\xd0\xb0 \xd1\x84\xd0\xb0\xd0\xb9\xd0\xbb\xd0\xb0\n',

'Hellodear123\n']



>>>


Стоит помнить, что кодировка наших строк, осталась такой же, как была в файле, Т.Е. utf-8. Тут напрашивается применение цикла, который пробежит по нашему списку и декодирует каждый элемент.

>>> lines_decode = []

>>> for i in lines:

...     lines_decode.append(i.decode('utf-8'))

...

>>> lines_decode

[u'\u041d\u0430\u0447\u0430\u043b\u043e \u0444\u0430\u0439\u043b\u0430\n', u'\u0

412\u0442\u043e\u0440\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u0444\u0

430\u0439\u043b\u0430\n', u'Hellodear123\n']

>>> print lines_decode[0]

Начало файла



>>> print lines_decode[1]

Вторая строка файла



>>> print lines_decode[2]

Hellodear123



>>>


Последний на сегодня метод получения содержимого файла - readline(). Этот метод возвращает текст построчно. За одно применение метода, вам будет возвращена каждая последующая строка файла.

>>> print f.readline().decode('utf-8')

Начало файла



>>> print f.readline().decode('utf-8')

Вторая строка файла



>>> print f.readline().decode('utf-8')

Hellodear123



>>>


Комментариев нет:

Отправить комментарий