Файлы - file

Python предоставляет встроенные функции для создания, записи и чтения файлов. Существует два типа файлов, которые могут быть обработаны в Python, обычные текстовые файлы и двоичные (бинарные) файлы (записанные на двоичном языке, 0 и 1).

  • text files (от англ. текстовые файлы): в этом типе файлов каждая строка текста заканчивается специальным символом EOL (конец строки), которая по умолчанию является символом новой строки '\n' в python.

  • binary files (от англ. двоичные файлы): в этом типе файла нет разделителя для строки, и данные сохраняются после преобразования его в понятный машинный двоичный язык.

Сосредоточимся на открытии, закрытии, чтении и записи данных в текстовом файле.

Режимы доступа к файлам

Access Mode - Режимы доступа определяют тип возможных операций в открытом файле. Это относится к тому, как файл будет использоваться после его открытия. Эти режимы также определяют местоположение дескриптора файла в файле. Дескриптор файла похож на курсор, который определяет, откуда данные должны быть прочитаны или записаны в файл. В питоне есть 6 режимов доступа:

  • Read Only 'r' (от англ. только чтение): открывает текстовый файл для чтения. Дескриптор располагается в начале файла. Если файл не существует, возникает ошибка ввода-вывода. Это также режим по умолчанию, в котором файл открывается.

  • Read and Write 'r+' (от англ. чтение и запись): открывает файл для чтения и записи. Дескриптор располагается в начале файла. Вызывает ошибку ввода-вывода, если файл не существует.

  • Write Only 'w' (от англ. только запись): открывает файл для записи. Для существующего файла данные усекаются и перезаписываются. Дескриптор располагается в начале файла. Создает файл, если файл не существует.

  • Write and Read 'w+' (от англ. запись и чтение): открывает файл для чтения и записи. Для существующего файла данные усекаются и перезаписываются. Дескриптор располагается в начале файла.

  • Append Only 'a' (от англ. только добавить): открывает файл для записи. Файл создается, если он не существует. Дескриптор располагается в конце файла. Записываемые данные будут вставлены в конце, после существующих данных.

  • Append and Read 'a+' (от англ. добавить и прочитать): открывает файл для чтения и записи. Файл создается, если он не существует. Дескриптор располагается в конце файла. Записываемые данные будут вставлены в конце, после существующих данных.

Открытие файла - open file

Открытие файла делается с помощью встроенной функции open(). Для этой функции не требуется импортировать модуль.

функции open() передают один или два аргумента. Первый – имя файла или имя с адресом, если файл находится не в том каталоге, где находится скрипт. Второй аргумент – режим, в котором открывается файл.

file_object = open(r"File_Name", "Access_Mode")
1

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

ПРИМЕЧАНИЕ

r ставится перед именем файла, чтобы символы в строке имени файла не обрабатывались как специальные символы. Например, если в адресе файла есть \temp, то \t обрабатывается как символ табуляции и возникает ошибка неверного адреса. R делает строку необработанной, то есть сообщает, что строка не имеет специальных символов. Символ r можно игнорировать, если файл находится в том же каталоге и адрес не размещается.

Если файл отсутствует, то открытие его в режиме w создаст новый файл. Бывают ситуации, когда надо гарантировано создать новый файл, избежав случайной перезаписи данных существующего. В этом случае вместо режима w используется режим x. В нем всегда создается новый файл для записи. Если указано имя существующего файла, то будет выброшено исключение. Потери данных в уже имеющемся файле не произойдет.

Если при вызове open() второй аргумент не указан, то файл открывается в режиме чтения как текстовый файл. Чтобы открыть файл как байтовый, дополнительно к букве режима чтения/записи добавляется символ b. Буква t обозначает текстовый файл. Поскольку это тип файла по умолчанию, то обычно ее не указывают.

Нельзя указывать только имя файла без его типа, то есть open('имя_файла', 'b') есть ошибка, даже если файл открывается на чтение. Правильно – open('имя_файла.тип_файла', 'rb'). Только текстовые файлы мы можем открыть командой open('имя_файла'), потому что и r и t подразумеваются по-умолчанию.

Функция open() возвращает объект файлового типа. Его надо либо сразу связать с переменной, чтобы не потерять, либо сразу прочитать.

Чтение - read file

С помощью файлового метода read() можно прочитать файл целиком или только определенное количество байт. Создайте в блокноте файл data.txt с таким содержимым:

# /data.txt
one - 1 - I
two - 2 - II
three - 3 - III
four - 4 - IV
five - 5 - V
1
2
3
4
5
6

Откроем его и почитаем:

file_read = open('data.txt')
print(file_read.read(10))      # 'one - 1 - '
print(file_read.read(2))       # 'I\n'
print(file_read.read())        # 'two - 2 - II\nthree - 3 - III\nfour - 4 - IV\nfive - 5 - V\n'
print(file_read.read())        # ''
print(type(file_read.read()))  # <class 'str'>
1
2
3
4
5
6

Сначала считываются первые десять байтов, которые равны десяти символам. Это не бинарный файл, но мы все равно можем читать по байтам. Последующий вызов read() считывает весь оставшийся текст. После этого объект файлового типа file_read становится пустым.

Заметим, что метод read() возвращает строку, и что конец строки считывается как \n.

Для того, чтобы читать файл построчно существует метод readline():

file_read = open('data.txt')
print(file_read.readline())    # 'one - 1 - I\n'
print(file_read.readline())    # 'two - 2 - II\n'
print(file_read.readline())    # 'three - 3 — III\n'
1
2
3
4

Метод .readlines() считывает сразу все строки и создает список:

file_read = open('data.txt')
print(file_read.readlines())   # ['one - 1 - I\n', 'two - 2 - II\n', 'three - 3 - III\n', 'four - 4 - IV\n', 'five - 5 - V\n']
1
2

Объект файлового типа относится к так называемым итерируемым объектам. Из таких объектов происходит последовательное извлечение элементов. Поэтому считывать данные из них можно сразу в цикле без использования методов чтения:

for line in open('data.txt'):
    print(line)
1
2

Результат выполнения:

one - 1 - I

two - 2 - II

three - 3 - III

four - 4 - IV

five - 5 - V

1
2
3
4
5
6
7
8
9
10

Здесь при выводе наблюдаются лишние пустые строки. Функция print() преобразует \n в переход на новую строку. К этому добавляет свой переход на новую строку. Создадим список строк файла без \n:

numbers = []
for line in open('data.txt'):
    numbers.append(line.strip())

print(numbers)         # ['one - 1 - I', 'two - 2 - II', 'three - 3 - III', 'four - 4 - IV', 'five - 5 - V']
1
2
3
4
5

Переменной line присваивается очередная строка файла. Метод line.strip() очищает стоку от лишних пробелов справа или с лева от стоки и удаляет \n.

Упражнения

  1. Создайте файл numbers.txt, содержащий несколько чисел, записанных через пробел:

    1 12  4
    
    15 40
    
    1
    2
    3

    Напишите программу, которая подсчитывает и выводит на экран общую сумму чисел, хранящихся в этом файле. Алгоритм должен быть универсальным. Числа могут быть различной длины, разделяться несколькими пробелами и записанными в несколько строк.

    Проверьте работу написанного алгоритма на новом файле new_numbers.txt:

    New initial data:
    
     37   8
    4 111 1000 1
    
    1
    2
    3
    4

    Проверьте корректность работы алгоритма. Общая сумма равна: 1233

  2. Создайте файл goods.txt, в котором хранится список покупок:

    Clothes  Prices
    
    jacket - 4 500
    socks   - 500
    umbrella - 900
    belt    - 1 000
    slippers - 90
    
    1
    2
    3
    4
    5
    6
    7

    Напишите программу, которая подсчитывает и выводит на экран общую сумму чисел, хранящихся в этом файле. Добавьте в файл записи покупок:

    ...
    backpack - 14 999.99
    flip-flops - 350,99
    fur coat  - 26 000
    
    1
    2
    3
    4

    Проверьте корректность работы алгоритма. Общая сумма равна: 48240.98

  3. Напишите программу с вопросами, с использованием генерации интерфейса. Алгоритм должен быть универсальным.

    Пример файла questions.txt:

    1. The capital of Russia is ...
    - London
    + Moscow
    - Berlin
    - Paris
    
    1
    2
    3
    4
    5

    Проверьте корректность работы генератора интерфейса, на примере измененного файла questions.txt:

    1. The capital of the Great Britain is ...
    + London
    - Moscow
    - Berlin
    - Paris
    - St.-Petersburg
    
    2. What country is European?
    - Japan
    - China
    + Spain
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    question

  4. Доработайте предыдущий вариант программы:

    • варианты ответа после вопроса выводятся в случайном порядке.
    • реализуйте проверку выбранных ответов.
    • подсчитайте количество правильных и не правильных ответов, выбранных пользователем.
    • замените вопросы в файле questions.txt, и проверьте работу программы с новыми вопросами.
    1. What sea with the name of the color does not exist?
    - Blacken
    - Red
    + Blue
    - Yellow
    - White
    
    2. Which country is the second largest in the world?
    + Canada
    -Russia
    -USA
    -China
      3. What are the tallest mountains in the world?
    Ural
    Andes
    + Himalayas
    Alps
    Caucasian
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

Запись в файл - write file

Запись в файл выполняется с помощью методов .write() и .writelines(). Во второй можно передать структуру данных:

list_numbers = ['tree', 'four']
file_write = open('new_data.txt', 'w')
print(file_write.write('one\n'))                # 4
print(file_write.write('two'))                  # 3
print(file_write.writelines(list_numbers))      # None
1
2
3
4
5

Метод .write() возвращает количество записанных символов. \n - символ переноса строки, считается за один символ.

В результате выполнения кода в появиться файл new_data.txt с текстом в нем

one
twotreefour
1
2

Закрытие файла - close file

После того как работа с файлом закончена, важно не забывать его закрыть, чтобы освободить место в памяти. Делается это с помощью файлового метода close(). Свойство файлового объекта closed позволяет проверить закрыт ли файл:

file_read.close()
print(file_read.closed)         # True
print(file_write.closed)        # False
1
2
3

Если файл открывается в заголовке цикла for line in open("file_name"), то видимо интерпретатор его закрывает при завершении работы цикла.

Oператор with

В Python имеется инструмент, применяя который может упростить чтение и редактирование файлов. Оператор with создает диспетчер контекста, который автоматически закрывает файл для вас, по окончанию работы в нем. Посмотрим, как это работает:

with open("data.txt") as data_file:
    print(data_file.read())
1
2

Синтаксис для оператора with ... as ... не сложен. Фактически, все, что мы делаем в данном примере, это:

data_file = open("test.txt")
1

Меняем на это:

with open("test.txt") as data_file:
1

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

Упражнения

  1. Напишите программу создающую файл week_days.txt со следующим содержимым:

    1. Monday
    2. Tuesday
    3. Wednesday
    4. Thursday
    5. Friday
    6. Saturday
    7. Sunday
    
    1
    2
    3
    4
    5
    6
    7
  2. Создайте файл data.txt со следующим содержимым:

    four - 4 - IV
    two - 2 - II
    one - 1 - I
    three - 3 - III
    five - 5 - V
    four - 4 - IV
    one - 1 - I
    
    1
    2
    3
    4
    5
    6
    7

    Напишите программу, которая открывает этот файл на чтение, построчно считывает из него данные и записывает строки в другой файл data_ru.txt, заменяя английские числительные русскими, которые содержатся в списке: ['один', 'два', 'три', 'четыре', 'пять'], определенном до открытия файлов.

Упражнения tkinter

  1. Напишите программу, которая сохраняет данные из Listbox() в текстовый файл.

  2. Напишите программу, загружающую содержимое текстового файла в виджет Listbox().

  3. Напишите программу, которая загружает данные из файла в Listbox(). Позволяет добавить и удалить данные и сохраняет изменения в файл.

  4. Напишите программу для составления списка вопросов. Левая сторона программы содержит:

    • поля подписей,
    • многострочное поле ввода вопроса,
    • многострочное поле ввода правильного ответа,
    • многострочное поля ввода неправильных вариантов ответа с вертикально полосой прокрутки,
    • кнопка добавления вопроса в правое многострочное текстовое поле, (предпросмотр).

    Правая сторона содержит:

    • правое многострочное текстовое поле (предпросмотр) с вертикально полосой прокрутки, с выводам всего документа вопросов.
    • кнопка сохранения текста в документ questions_new.txt, с вызовом диалогового окна выбора документа.

    Реализация:

    • Для многострочных полей реализовать перенос по словам,
    • Перед добавлением вопроса из левой формы, реализовать проверку на пустоту всех полей.
    • Реализовать множественное добавление вопросов, с увеличением номера следующего вопроса.
    • Перед сохранением документа реализовать предупреждение перезаписи документа и вопроса согласия пользователя на перезапись.
    • После переноса вопроса из левой стороны в правую, все поля левой стороны очищаются.
    • Задайте ограничение минимального размера окна 400х300.
    • При изменении размера окна, интерфейс должен отображаться корректно.

    Пример вопроса:

    Which country is no more?
    
    + Rome
    + USSR
    
    - Finland
    - Poland
    
    1
    2
    3
    4
    5
    6
    7

    question