ээдд. Прохоренок_Н_А__Дронов_В_А_Python_3_и_PyQt_5_Разработка_приложен. Николай Прохоренок Владимир Дронов
Скачать 7.92 Mb.
|
292 Часть I. Основы языка Python >>> # Текстовый режим (символ \r удаляется) >>> with open(r"file.txt", "r") as f: for line in f: print(repr(line)) 'String1\n' 'String2' Для ускорения работы производится буферизация записываемых данных. Информация из буфера записывается в файл полностью только в момент закрытия файла или после вызова функции или метода flush() . В необязательном параметре buffering можно указать размер буфера. Если в качестве значения указан 0 , то данные будут сразу записываться в файл (значение допустимо только в бинарном режиме). Значение 1 используется при построчной записи в файл (значение допустимо только в текстовом режиме), другое положительное число задает примерный размер буфера, а отрицательное значение (или отсутствие значе- ния) означает установку размера, применяемого в системе по умолчанию. По умолчанию текстовые файлы буферизуются построчно, а бинарные — частями, размер которых интер- претатор выбирает самостоятельно в диапазоне от 4096 до 8192 байтов. При использовании текстового режима (задается по умолчанию) при чтении производится попытка преобразовать данные в кодировку Unicode, а при записи выполняется обратная операция — строка преобразуется в последовательность байтов в определенной кодировке. По умолчанию назначается кодировка, применяемая в системе. Если преобразование невоз- можно, возбуждается исключение. Указать кодировку, которая будет использоваться при записи и чтении файла, позволяет параметр encoding . Для примера запишем данные в коди- ровке UTF-8: >>> f = open(r"file.txt", "w", encoding="utf-8") >>> f.write("Строка") # Записываем строку в файл 6 >>> f.close() # Закрываем файл Для чтения этого файла следует явно указать кодировку при открытии файла: >>> with open(r"file.txt", "r", encoding="utf-8") as f: for line in f: print(line) Строка При работе с файлами в кодировках UTF-8, UTF-16 и UTF-32 следует учитывать, что в на- чале файла могут присутствовать служебные символы, называемые сокращенно BOM (Byte Order Mark, метка порядка байтов). Для кодировки UTF-8 эти символы являются необяза- тельными, и в предыдущем примере они не были добавлены в файл при записи. Чтобы сим- волы были добавлены, в параметре encoding следует указать значение utf-8-sig . Запишем строку в файл в кодировке UTF-8 с BOM: >>> f = open(r"file.txt", "w", encoding="utf-8-sig") >>> f.write("Строка") # Записываем строку в файл 6 >>> f.close() # Закрываем файл Теперь прочитаем файл с разными значениями в параметре encoding : >>> with open(r"file.txt", "r", encoding="utf-8") as f: for line in f: print(repr(line)) Глава 16. Работа с файлами и каталогами 293 '\ufeffСтрока' >>> with open(r"file.txt", "r", encoding="utf-8-sig") as f: for line in f: print(repr(line)) 'Строка' В первом примере мы указали значение utf-8 , поэтому маркер BOM был прочитан из файла вместе с данными. Во втором примере указано значение utf-8-sig , поэтому маркер BOM не попал в результат. Если неизвестно, есть ли маркер в файле, и необходимо получить данные без маркера, то следует всегда указывать значение utf-8-sig при чтении файла в кодировке UTF-8. Для кодировок UTF-16 и UTF-32 маркер BOM является обязательным. При указании значе- ний utf-16 и utf-32 в параметре encoding обработка маркера производится автоматически. При записи данных маркер автоматически вставляется в начало файла, а при чтении он не попадает в результат. Запишем строку в файл, а затем прочитаем ее из файла: >>> with open(r"file.txt", "w", encoding="utf-16") as f: f.write("Строка") 6 >>> with open(r"file.txt", "r", encoding="utf-16") as f: for line in f: print(repr(line)) 'Строка' При использовании значений utf-16-le , utf-16-be , utf-32-le и utf-32-be маркер BOM не- обходимо самим добавить в начало файла, а при чтении удалить его. В параметре errors можно указать уровень обработки ошибок. Возможные значения: "strict" (при ошибке возбуждается исключение ValueError — значение по умолчанию), "replace" (неизвестный символ заменяется символом вопроса или символом с кодом \ufffd ), "ignore" (неизвестные символы игнорируются), "xmlcharrefreplace" (неизвестный символ заменяется последовательностью xxx; ) и "backslashreplace" (неизвестный сим- вол заменяется последовательностью \uxxxx ). Параметр newline задает режим обработки символов конца строк. Поддерживаемые им зна- чения таковы: None (значение по умолчанию) — выполняется стандартная обработка символов конца строки. Например, в Windows при чтении символы \r\n преобразуются в символ \n , а при записи производится обратное преобразование; "" (пустая строка) — обработка символов конца строки не выполняется; "<Специальный символ>" — указанный специальный символ используется для обозначе- ния конца строки, и никакая дополнительная обработка не выполняется. В качестве спе- циального символа можно указать лишь \r\n , \r и \n 16.2. Методы для работы с файлами После открытия файла функция open() возвращает объект, с помощью которого произво- дится дальнейшая работа с файлом. Тип объекта зависит от режима открытия файла и буферизации. Рассмотрим основные методы: 294 Часть I. Основы языка Python close() — закрывает файл. Так как интерпретатор автоматически удаляет объект, когда на него отсутствуют ссылки, в небольших программах файл можно не закрывать явно. Тем не менее, явное закрытие файла является признаком хорошего стиля программи- рования. Кроме того, при наличии незакрытого файла генерируется предупреждающее сообщение: "ResourceWarning: unclosed file" Язык Python поддерживает протокол менеджеров контекста. Этот протокол гарантирует закрытие файла вне зависимости от того, произошло исключение внутри блока кода или нет: with open(r"file.txt", "w", encoding="cp1251") as f: f.write("Строка") # Записываем строку в файл # Здесь файл уже закрыт автоматически write(<Данные>) — записывает данные в файл. Если в качестве параметра указана стро- ка, файл должен быть открыт в текстовом режиме, а если указана последовательность байтов — в бинарном. Помните, что нельзя записывать строку в бинарном режиме и по- следовательность байтов в текстовом режиме. Метод возвращает количество записанных символов или байтов. Пример записи в файл: >>> # Текстовый режим >>> f = open(r"file.txt", "w", encoding="cp1251") >>> f.write("Строка1\nСтрока2") # Записываем строку в файл 15 >>> f.close() # Закрываем файл >>> # Бинарный режим >>> f = open(r"file.txt", "wb") >>> f.write(bytes("Строка1\nСтрока2", "cp1251")) 15 >>> f.write(bytearray("\nСтрока3", "cp1251")) 8 >>> f.close() writelines(<Последовательность>) — записывает последовательность в файл. Если все элементы последовательности являются строками, файл должен быть открыт в тексто- вом режиме. Если все элементы являются последовательностями байтов, то файл должен быть открыт в бинарном режиме. Пример записи элементов списка: >>> # Текстовый режим >>> f = open(r"file.txt", "w", encoding="cp1251") >>> f.writelines(["Строка1\n", "Строка2"]) >>> f.close() >>> # Бинарный режим >>> f = open(r"file.txt", "wb") >>> arr = [bytes("Строка1\n", "cp1251"), bytes("Строка2", "cp1251")] >>> f.writelines(arr) >>> f.close() writable() — возвращает True , если файл поддерживает запись, и False — в противном случае: >>> f = open(r"file.txt", "r") # Открываем файл для чтения >>> f.writable() False Глава 16. Работа с файлами и каталогами 295 >>> f = open(r"file.txt", "w") # Открываем файл для записи >>> f.writable() True read([<Количество>]) — считывает данные из файла. Если файл открыт в текстовом режиме, возвращается строка, а если в бинарном — последовательность байтов. Если параметр не указан, возвращается содержимое файла от текущей позиции указателя до конца файла: >>> # Текстовый режим >>> with open(r"file.txt", "r", encoding="cp1251") as f: f.read() 'Строка1\nСтрока2' >>> # Бинарный режим >>> with open(r"file.txt", "rb") as f: f.read() b'\xd1\xf2\xf0\xee\xea\xe01\n\xd1\xf2\xf0\xee\xea\xe02' Если в качестве параметра указать число, то за каждый вызов будет возвращаться ука- занное количество символов или байтов. Когда достигается конец файла, метод возвра- щает пустую строку: >>> # Текстовый режим >>> f = open(r"file.txt", "r", encoding="cp1251") >>> f.read(8) # Считываем 8 символов 'Строка1\n' >>> f.read(8) # Считываем 8 символов 'Строка2' >>> f.read(8) # Достигнут конец файла '' >>> f.close() readline([<Количество>]) — считывает из файла одну строку при каждом вызове. Если файл открыт в текстовом режиме, возвращается строка, а если в бинарном — последова- тельность байтов. Возвращаемая строка включает символ перевода строки. Исключени- ем является последняя строка — если она не завершается символом перевода строки, то таковой добавлен не будет. При достижении конца файла возвращается пустая строка: >>> # Текстовый режим >>> f = open(r"file.txt", "r", encoding="cp1251") >>> f.readline(), f.readline() ('Строка1\n', 'Строка2') >>> f.readline() # Достигнут конец файла '' >>> f.close() >>> # Бинарный режим >>> f = open(r"file.txt", "rb") >>> f.readline(), f.readline() (b'\xd1\xf2\xf0\xee\xea\xe01\n', b'\xd1\xf2\xf0\xee\xea\xe02') >>> f.readline() # Достигнут конец файла b'' >>> f.close() 296 Часть I. Основы языка Python Если в необязательном параметре указано число, считывание будет выполняться до тех пор, пока не встретится символ новой строки ( \n ), символ конца файла или из файла не будет прочитано указанное количество символов. Иными словами, если количество сим- волов в строке меньше значения параметра, то будет считана одна строка, а не указанное количество символов, а если количество символов в строке больше, то возвращается указанное количество символов: >>> f = open(r"file.txt", "r", encoding="cp1251") >>> f.readline(2), f.readline(2) ('Ст', 'ро') >>> f.readline(100) # Возвращается одна строка, а не 100 символов 'ка1\n' >>> f.close() readlines() — считывает все содержимое файла в список. Каждый элемент списка бу- дет содержать одну строку, включая символ перевода строки. Исключением является последняя строка — если она не завершается символом перевода строки, таковой добав- лен не будет. Если файл открыт в текстовом режиме, возвращается список строк, а если в бинарном — список объектов типа bytes : >>> # Текстовый режим >>> with open(r"file.txt", "r", encoding="cp1251") as f: f.readlines() ['Строка1\n', 'Строка2'] >>> # Бинарный режим >>> with open(r"file.txt", "rb") as f: f.readlines() [b'\xd1\xf2\xf0\xee\xea\xe01\n', b'\xd1\xf2\xf0\xee\xea\xe02'] __next__() — считывает одну строку при каждом вызове. Если файл открыт в текстовом режиме, возвращается строка, а если в бинарном — последовательность байтов. При достижении конца файла возбуждается исключение StopIteration : >>> # Текстовый режим >>> f = open(r"file.txt", "r", encoding="cp1251") >>> f.__next__(), f.__next__() ('Строка1\n', 'Строка2') >>> f.__next__() # Достигнут конец файла Traceback (most recent call last): File " ", line 1, in StopIteration >>> f.close() Благодаря методу __next__() мы можем перебирать файл построчно в цикле for . Цикл for на каждой итерации будет автоматически вызывать метод __next__() . Для примера выведем все строки, предварительно удалив символ перевода строки: >>> f = open(r"file.txt", "r", encoding="cp1251") >>> for line in f: print(line.rstrip("\n"), end=" ") Строка1 Строка2 >>> f.close() Глава 16. Работа с файлами и каталогами 297 flush() — принудительно записывает данные из буфера на диск; fileno() — возвращает целочисленный дескриптор файла. Возвращаемое значение все- гда будет больше числа 2, т. к. число 0 закреплено за стандартным вводом stdin , 1 — за стандартным выводом stdout , а 2 — за стандартным выводом сообщений об ошибках stderr : >>> f = open(r"file.txt", "r", encoding="cp1251") >>> f.fileno() # Дескриптор файла 3 >>> f.close() truncate([<Количество>]) — обрезает файл до указанного количества символов (если задан текстовый режим) или байтов (в случае бинарного режима). Метод возвращает новый размер файла: >>> f = open(r"file.txt", "r+", encoding="cp1251") >>> f.read() 'Строка1\nСтрока2' >>> f.truncate(5) 5 >>> f.close() >>> with open(r"file.txt", "r", encoding="cp1251") as f: f.read() 'Строк' tell() — возвращает позицию указателя относительно начала файла в виде целого чис- ла. Обратите внимание на то, что в Windows метод tell() считает символ \r как допол- нительный байт, хотя этот символ удаляется при открытии файла в текстовом режиме: >>> with open(r"file.txt", "w", encoding="cp1251") as f: f.write("String1\nString2") 15 >>> f = open(r"file.txt", "r", encoding="cp1251") >>> f.tell() # Указатель расположен в начале файла 0 >>> f.readline() # Перемещаем указатель 'String1\n' >>> f.tell() # Возвращает 9 (8 + '\r'), а не 8 !!! 9 >>> f.close() Чтобы избежать этого несоответствия, следует открывать файл в бинарном режиме, а не в текстовом: >>> f = open(r"file.txt", "rb") >>> f.readline() # Перемещаем указатель b'String1\r\n' >>> f.tell() # Теперь значение соответствует 9 >>> f.close() 298 Часть I. Основы языка Python seek(<Смещение>[, <Позиция>]) — устанавливает указатель в позицию, имеющую за- данное <Смещение> относительно параметра <Позиция> . В качестве параметра <Позиция> могут быть указаны следующие атрибуты из модуля io или соответствующие им значе- ния: • io.SEEK_SET или 0 — начало файла (значение по умолчанию); • io.SEEK_CUR или 1 — текущая позиция указателя. Положительное значение смещения вызывает перемещение к концу файла, отрицательное — к его началу; • io.SEEK_END или 2 — конец файла. Выведем значения этих атрибутов: >>> import io >>> io.SEEK_SET, io.SEEK_CUR, io.SEEK_END (0, 1, 2) Пример использования метода seek() : >>> import io >>> f = open(r"file.txt", "rb") >>> f.seek(9, io.SEEK_CUR) # 9 байтов от указателя 9 >>> f.tell() 9 >>> f.seek(0, io.SEEK_SET) # Перемещаем указатель в начало 0 >>> f.tell() 0 >>> f.seek(-9, io.SEEK_END) # -9 байтов от конца файла 7 >>> f.tell() 7 >>> f.close() seekable() — возвращает True , если указатель файла можно сдвинуть в другую пози- цию, и False — в противном случае: >>> f = open(r"C:\temp\new\file.txt", "r") >>> f.seekable() True Помимо методов, объекты файлов поддерживают несколько атрибутов: name — имя файла; mode — режим, в котором был открыт файл; closed — возвращает True , если файл был закрыт, и False — в противном случае: >>> f = open(r"file.txt", "r+b") >>> f.name, f.mode, f.closed ('file.txt', 'rb+', False) >>> f.close() >>> f.closed True Глава 16. Работа с файлами и каталогами 299 encoding — название кодировки, которая будет использоваться для преобразования строк перед записью в файл или при чтении. Атрибут доступен только в текстовом режиме. Обратите также внимание на то, что изменить значение атрибута нельзя, поскольку он доступен только для чтения: >>> f = open(r"file.txt", "a", encoding="cp1251") >>> f.encoding 'cp1251' >>> f.close() Стандартный вывод stdout также является файловым объектом. Атрибут encoding этого объекта всегда содержит кодировку устройства вывода, поэтому строка преобразуется в последовательность байтов в правильной кодировке. Например, при запуске с помощью двойного щелчка на значке файла атрибут encoding будет иметь значение "cp866" , а при запуске в окне Python Shell редактора IDLE — значение "cp1251" : >>> import sys >>> sys.stdout.encoding 'cp1251' buffer — позволяет получить доступ к буферу. Атрибут доступен только в текстовом режиме. С помощью этого объекта можно записать последовательность байтов в тексто- вый поток: >>> f = open(r"file.txt", "w", encoding="cp1251") >>> f.buffer.write(bytes("Строка", "cp1251")) 6 >>> f.close() 16.3. Доступ к файлам с помощью модуля os Модуль os содержит дополнительные низкоуровневые функции, позволяющие работать с файлами. Функциональность этого модуля зависит от используемой операционной систе- мы. Получить название используемой версии модуля можно с помощью атрибута name В любой из поддерживаемых Python версий операционной системы Windows этот атрибут возвращает значение "nt" : >>> import os >>> os.name # Значение в ОС Windows 8 'nt' Для доступа к файлам предназначены следующие функции из модуля os : open(<Путь к файлу>, <Режим>[, mode=0o777]) — открывает файл и возвращает цело- численный дескриптор, с помощью которого производится дальнейшая работа с файлом. Если файл открыть не удалось, возбуждается исключение OSError или одно из исключе- ний, являющихся его подклассами (мы поговорим о них в конце этой главы). В парамет- ре <Режим> в операционной системе Windows могут быть указаны следующие флаги (или их комбинация через символ | ): • os.O_RDONLY — чтение; • os.O_WRONLY — запись; • os.O_RDWR — чтение и запись; • os.O_APPEND — добавление в конец файла; 300 Часть I. Основы языка Python • os.O_CREAT — создать файл, если он не существует и если не указан флаг os.O_EXCL ; • os.O_EXCL — при использовании совместно с os.O_CREAT указывает, что создаваемый файл изначально не должен существовать, в противном случае будет сгенерировано исключение |