# Отчет по теме 6 Коломейцев Дмитрий, А-02-23 ## Ввод-вывод данных и операции с файлами ### 1. Установка рабочего каталога. Создание рабочего протокола. В оболочке IDLE установил рабочий каталог: ![alt text](pics/{72010710-3A40-46AA-BB43-958FFCA4E8BE}.png) ### 2. Вывод данных на экран дисплея. #### 2.1. Вывод в командной строке. При вводе команд в интерактивном режиме интерпретатор сам показывает значение переменной, если просто написать её имя. Внутри скриптов и функций такой способ не работает, там нужен явный вывод. ```py >>> stroka = "Автоматизированная система управления" >>> stroka 'Автоматизированная система управления' ``` #### 2.2. Вывод с использованием функции print. Самый распространённый способ вывода данных на экран - функция print. Она позволяет вывести несколько значений за один вызов. ```py >>> fff = 234; gg = "Значение температуры =" >>> print(gg, fff) # Вывод нескольких объектов через запятую Значение температуры = 234 ``` Через параметр sep можно задать символ (или строку), который будет разделять выводимые элементы. ```py >>> print(gg, fff, sep = "/") # Вывод объектов с заданным разделителем Значение температуры =/234 ``` Через параметр end можно указать, что выводить в конце строки вместо перехода на новую строку по умолчанию. ```py >>> print(gg, fff, sep = "/", end = "***"); print("____") # Вывод объектов с указанным окончанием строки Значение температуры =/234***____ ``` Функция print поддерживает вывод многострочных строк, которые можно задавать через тройные кавычки, а также можно выводить длинный текст, разбитый на несколько аргументов. ```py >>> print("""Здесь может выводиться ... большой текст, ... занимающий несколько строк""") Здесь может выводиться большой текст, занимающий несколько строк ``` ```py >>> print("Здесь может выводиться", ... "большой текст", ... "занимающий несколько строк") Здесь может выводиться большой текст занимающий несколько строк ``` #### 2.3. Вывод с использованием метода write объекта sys.stdout. Стандартный способ вывода данных - через поток вывода stdout, находящийся в модуле sys. В данном методе не происходит автоматический переход на новую строку при последовательном его использовании, поэтому необходимо вручную добавлять символ "\n". ```py >>> import sys >>> sys.stdout.write("Функция write") # Вывод строки с помощью метода write Функция write13 # Число 13 в конце - количество символов в строке >>> sys.stdout.write("Функция write\n") Функция write 14 ``` ### 3. Ввод данных с клавиатуры. Для ввода данных с клавиатуры используется функция input, ранее изученная. ```py >>> pws = input("Введите пароль: ") Введите пароль: 1234567 >>> pws '1234567' >>> type(pws) ``` Ввод значений можно контролировать с помощью циклов и break: ```py >>> while True: ... znach = float(input("Задайте коэф. усиления = ")) ... if znach < 17.5 or znach > 23.8: ... print("Ошибка!") ... else: ... break ... Задайте коэф. усиления = 15.4 Ошибка! Задайте коэф. усиления = 21.6 >>> ``` Также с помощью оператора ввода можно вычислять значения математических выражений ```py >>> import math >>> print(eval(input("Введите выражение для расчета: "))) Введите выражение для расчета: math.log10(23 / (1 + math.exp(-3.24))) 1.34504378689765 ``` ### 4. Ввод-вывод при работе с файлами. При работе с файлом необходимо указывать источник данных - полное имя файла с путем доступа к его расположению. #### 4.1. Функции для работы с путём к файлу. Если файл находится в текущем рабочем каталоге, то для получения полного пути проще сначала получить путь до рабочего каталога. Сделать это можно с помощью функции getcwd модуля os. ```py >>> import os >>> os.getcwd() # Отображение текущего рабочего каталога '/home/s0ba4/mpei/python-labs/TEMA6' >>> path = os.getcwd() >>> path '/home/s0ba4/mpei/python-labs/TEMA6' ``` В этом модуле есть функции, для создания и удалений директорий, а также проверки их наличия. ```py >>> os.mkdir("New directory") >>> os.mkdir("Another new directory") ``` ![alt text](pics/{C1999A98-CC84-4CE8-ABD3-60508308BC88}.png) ```py >>> os.rmdir("Another new directory") ``` ![alt text](pics/{9052F00F-49B1-4B6C-915A-DF6D9C0F2826}.png) ```py >>> os.path.isdir("New directory"); os.path.isdir("ABCDEF") # Проверка наличия директории в рабочем каталоге True False ``` Также полный путь доступа к файлу можно получить с помощью отдельной функции abspath. Затем из него можно выделить путь к директории, содержащей файл, и имя самого файла с помощью соответствующих функций dirname и basename. ```py >>> fil = os.path.abspath("oplata.dbf") # Получение полного пути к файлу >>> fil '/home/s0ba4/mpei/python-labs/TEMA6\\oplata.dbf' >>> drkt = os.path.dirname(fil) # Выделение пути доступа к файлу >>> drkt '/home/s0ba4/mpei/python-labs/TEMA6' >>> name = os.path.basename(fil) # Выделение имени файла >>> name 'oplata.dbf' >>> directory, fileName = os.path.split(fil) # Одновременное выделение пути доступа к файлу и его имени >>> directory '/home/s0ba4/mpei/python-labs/TEMA6' >>> fileName 'oplata.dbf' ``` Проверка того, указывает ли путь на существующий файл, осуществляется с помощью функции isfile. ```py >>> os.path.isfile(fil) # Проверка пути к файлу True >>> os.path.isfile("ABCDEF.txt") False ``` #### 4.2. Общая схема работы с файлом. Для обмена данными с файлом необходимо выполнить следующие операции: * Открытие файла с указанием его имени и цели (чтение, запись, добавление данных); * Выполнение одной или нескольких операций обмена данными с файлом; * Закрытие файла. #### 4.3. Открытие файла для записи и чтения файла. Для открытия файла используется функция open, в которой необходимо указывать путь и имя открывающегося файла и цель его использования. Имена аргументов в данной функции можно опускать, но тогда сами аргументы должны идти в правильном порядке. Если же файл находится в текущем рабочем каталоге, то полный путь к нему можно не указывать, будет достаточно только его имени. Различные значения аргумента mode: * w - запись/перезапись файла * w+ - чтение и запись/перезапись файла * r - только чтение существующего файла * r+ - чтение и/или запись в существующий файл * a - запись в конец существующего файла * a+ - запись в конец существующего файла с возможностью чтения ```py >>> fp = open(file = drkt + "\\zapis1.txt", mode = "w") # Открытие файла с явным указанием пути и цели использования >>> fp = open(drkt + "\\zapis1.txt", "w") # Открытие файла без указания имен аргументов >>> fp = open("zapis1.txt", "w") # Открытие файла, путь к которому совпадает с рабочим каталогом >>> type(fp) >>> dir(fp) ['_CHUNK_SIZE', 'class', 'del', 'delattr', 'dict', 'dir', 'doc', 'enter', 'eq', 'exit', 'format', 'ge', 'getattribute', 'getstate', 'gt', 'hash', 'init', 'init_subclass', 'iter', 'le', 'lt', 'ne', 'new', 'next', 'reduce', 'reduce_ex', 'repr', 'setattr', 'sizeof', 'str', 'subclasshook', '_checkClosed', '_checkReadable', '_checkSeekable', '_checkWritable', '_finalizing', 'buffer', 'close', 'closed', 'detach', 'encoding', 'errors', 'fileno', 'flush', 'isatty', 'line_buffering', 'mode', 'name', 'newlines', 'read', 'readable', 'readline', 'readlines', 'reconfigure', 'seek', 'seekable', 'tell', 'truncate', 'writable', 'write', 'write_through', 'writelines'] >>> fp1 = open(drkt + "\\zapis2.bin", "wb+") # Открытие бинарного файла ``` #### 4.4. Закрытие файла. После завершения работы с файлом его необходимо закрывать для обеспечения сохранности его содержимого. Это делается с помощью функции close, применяемой к файловой переменной. ```py >>> fp.close() ``` #### 4.5. Запись информации в файл. Стандартный вариант записи в файл - использование метода write. ```py >>> sps = list(range(1, 13)) >>> sps [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] >>> fp2 = open("zapis3.txt", "w") >>> fp2.write(str(sps[:4]) + "\n") # Запись в файл первых 4 значений + переход на новую строку 13 >>> fp2.write(str(sps[4:8]) + "\n") 13 >>> fp2.write(str(sps[8:]) + "\n") 16 >>> fp2.close() ``` ![alt text](pics/{1C5F9727-9048-44C1-8C12-B6221EEBD909}.png) Запись данных также можно проводить внутри цикла: ```py >>> sps3 = [["Иванов И.", 1], ["Петров П.", 2], ["Сидоров С.", 3]] >>> fp3 = open("zapis4.txt", "w") >>> for i in range(len(sps3)): ... stroka4 = sps3[i][0] + " " + str(sps3[i][1]) ... fp3.write(stroka4) ... 11 11 12 >>> fp3.close() ``` ![alt text](pics/{9A4C6E7E-38B4-41F6-96E7-12869DEB96B5}.png) Данные записались без разделителей, это нужно исправить: ```py >>> gh = open("zapis5.txt", "w") >>> for r in sps3: ... gh.write(r[0] + " " + str(r[1]) + "\n") ... 12 12 13 >>> gh.close() ``` ![alt text](pics/{26A396C9-A623-47DE-8903-39CBB4436F41}.png) При ручном добавлении перехода на новую строку данные записываются в файл в более презентабельном виде. Весь этот цикл можно представить в одной строчке: ```py >>> for r in sp3: gh.write(r[0] + " " + str(r[1]) + "\n") ``` #### 4.6. Чтение информации из текстового файла внутри цикла. Чтение данных из файла происходит последовательно, начиная с некоторого символа. В качестве примера прочитан ранее созданный файл zapis3.txt: ```py >>> sps1 = [] >>> fp = open("zapis3.txt") >>> for stroka in fp: ... stroka = stroka.rstrip("\n") # Удаление символа \n с конца строки ... stroka = stroka.replace("[", "") ... stroka = stroka.replace("]", "") ... sps1 = sps1 + stroka.split(",") ... >>> fp.close() >>> sps1 ['1', ' 2', ' 3', ' 4', '5', ' 6', ' 7', ' 8', '9', ' 10', ' 11', ' 12'] ``` Как видно из результата, прочитанные данные отличаются от исходных. Исправить это можно, внеся небольшие изменения в процесс чтения: ```py >>> sps2 = [] >>> fp = open("zapis3.txt") >>> for stroka in fp: ... stroka = stroka.rstrip("\n") ... stroka = stroka.replace("[", "").replace("]", "").replace(" ", "") ... sps2 = sps2 + [int(x) for x in stroka.split(",")] ... >>> fp.close() >>> sps2 ... [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] ``` #### 4.7. Чтение информации с помощью метода read. Метод read читает содержимое файла как одну строку. Если указать аргумент (число), будет прочитано только заданное количество символов, а без аргумента метод возвращает весь оставшийся текст файла, начиная с текущей позиции. ```py >>> fp = open("zapis3.txt") >>> stroka1 = fp.read(12) # Чтение первых 12 символов >>> stroka2 = fp.read() # Чтение файла полностью >>> fp.close() >>> stroka1 '[1, 2, 3, 4]' >>> stroka2 '\n[5, 6, 7, 8]\n[9, 10, 11, 12]\n' ``` #### 4.8. Чтение информации с помощью методов readline и readlines. Метод readline считывает одну строку от текущей позиции. Повторные вызовы readline читают следующие строки файла. Метод readlines возвращает список всех строк файла, каждая строка представлена отдельным элементом списка. ```py >>> fp = open("zapis3.txt") >>> stroka1 = fp.readline() # Чтение первой строки файла >>> stroka2 = fp.readline() # Чтение второй строки файла >>> fp.close() >>> fp = open("zapis3.txt") >>> stroka3 = fp.readlines() # Чтение всех строк файла >>> fp.close() >>> stroka1 '[1, 2, 3, 4]\n' >>> stroka2 '[1, 2, 3, 4]\n' >>> stroka3 ['[1, 2, 3, 4]\n', '[1, 2, 3, 4]\n', '[9, 10, 11, 12]\n'] ``` #### 4.9. Ввод-вывод объектов с использованием функции из модуля pickle. Для работы с бинарными файлами можно пользоваться функциями из модуля pickle. Примером этого может послужить запись объекта-множества в бинарный файл: ```py >>> import pickle >>> mnoz1 = {"pen", "book", "pen", "iPhone", "table", "book"} >>> fp = open("zapis6.mnz", "wb") >>> pickle.dump(mnoz1, fp) # Запись объекта в файл >>> fp.close() ``` Функция pickle.dump записывает объект в файл в бинарном виде, поэтому содержимое такого файла в текстовом редакторе выглядит нечитаемо. ![alt text](pics/{206E90CF-F3FD-42A7-BFCC-ABEC1176FDA2}.png) Для восстановления объекта из файла применяется функция pickle.load, при этом объект получается в том же виде, как и при записи. ```py >>> fp = open("zapis6.mnz", "rb") >>> mnoz2 = pickle.load(fp) # Получение объекта из файла >>> fp.close() >>> mnoz2 {'book', 'iPhone', 'table', 'pen'} >>> mnoz1 == mnoz2 True ``` Важно подметить, что при считывании из файла объекты имеют тот же порядок, что и при их записи в него: ```py >>> fp = open("zapis7.2ob", "wb") >>> pickle.dump(mnoz1, fp) >>> pickle.dump(sps3, fp) >>> fp.close() >>> fp = open("zapis7.2ob", "rb") >>> obj1 = pickle.load(fp) # Получение объекта, записанного первым >>> obj2 = pickle.load(fp) # Получение объекта, записанного вторым >>> fp.close() >>> obj1 {'book', 'iPhone', 'table', 'pen'} >>> obj2 [['Иванов И.', 1], ['Петров П.', 2], ['Сидоров С.', 3]] ``` ### 5. Перенаправление потоков ввода и вывода данных. Потоки ввода-вывода можно перенаправлять, например в файл: ```py >>> import sys >>> vr_out = sys.stdout # Сохранение текущего потока вывода >>> fc = open("Stroka.txt", "w") >>> sys.stdout = fc # Перезапись потока вывода с экрана на файл >>> print("Запись строки в файл") >>> fc.close() >>> sys.stdout = vr_out # Возвращение истинного значения потока вывода >>> print("Запись строки на экран") Запись строки на экран ``` В результате данных действий строка "Запись строки в файл" записалась в файл Stroka.txt: ![alt text](pics/image.png) Аналогичную операцию можно провести и для потока ввода: ```py >>> tmp_in = sys.stdin # Сохранение текущего потока ввода >>> fd = open("Stroka.txt", "r") >>> sys.stdin = fd >>> sys.stdin <_io.TextIOWrapper name='Stroka.txt' mode='r' encoding='cp1251'> >>> while True: ... try: ... line = input() # Чтение строки из файла ... print(line) ... except EOFError: ... break ... Запись строки в файл >>> fd.close() >>> sys.stdin = tmp_in # Возвращение истинного значения потока ввода ``` ### 6. Завершение работы со средой. Сохранил файлы отчета в своем рабочем каталоге и закончил сеанс работы с IDLE.