8 способов использования функции open() в Python
Перейти по ссылкам
- Откройте файл и прочитайте его содержимое
- Использование ключевого слова with для автоматического закрытия файла
- Скопировать файл с помощью чтения и записи
- Создать новый текстовый файл
- Записывать в журнал, добавляя данные
- Используйте буферизацию для управления сохранением файлов
- Укажите кодировку для корректной поддержки UTF-8
- Обрабатывать неправильно сформированные файлы с помощью параметра Errors
Функция open в Python должна быть вашим первым выбором, когда вы хотите прочитать содержимое файла. Передайте ей имя файла, и вы получите универсальный объект, позволяющий читать и записывать данные как в текстовом, так и в бинарном формате.
Эти примеры показывают, насколько гибкой является функция, обеспечивая поддержку различных режимов, буферизации, кодирования и других возможностей.
Откройте файл и прочитайте его содержимое
Функция open() имеет довольно сложную сигнатуру, но в самых простых случаях вы можете использовать её для открытия текстового файла следующим образом:
f = open(filename)
По умолчанию Python открывает этот файл в режиме чтения, что означает, что вы можете только читать из него. Это идеально подходит для файлов конфигурации, статических файлов данных и … Это также делает этот распространённый случай кратким и легко запоминающимся.
Функция open() возвращает объект файла, который вы затем можете использовать для выполнения различных задач, включая чтение полного содержимого файла:
f = open("/usr/share/dict/words") text = f.read() print(text)
Обратите внимание, что этот простой фрагмент кода приведет к возникновению исключения в Python, если файл не существует:
Один файл, который гарантированно существует, — это скрипт, который вы запускаете, и Python делает его доступным в специальной переменной __file__. Это упрощает написание скрипта, который выводит свой собственный исходный код, иначе называемого квином:
f = open(__file__) text = f.read() print(text)
Если быть очень строгим, это не совсем квайн, потому что чтение файла считается обманом.
Использование ключевого слова with для автоматического закрытия файла
Когда Python открывает файл, он выделяет системные ресурсы для этого файла, которые затем использует для будущих операций, таких как чтение и запись. Если ваша программа выполнится до конца, Python должен освободить эти ресурсы, делая их доступными для других процессов, которые могут выполняться в вашей системе. Однако это не гарантировано, поэтому всегда следует убедиться, что ресурсы освобождены корректно. Самый простой способ сделать это — явно вызвать метод close() для вашего файла, когда вы знаете, что завершили работу с ним:
f = open("/usr/share/dict/words") text = f.read() f.close()
Старайтесь закрывать файл как можно скорее. Например, если вы открыли файл, прочитали его содержимое, а затем обрабатываете это содержимое, постарайтесь закрыть файл сразу после его прочтения. Нет необходимости держать файл открытым, пока вы обрабатываете данные, которые уже считали в переменную.
Но проблемы всё ещё могут возникнуть: что если вызов close() не выполнится должным образом? Чтобы обойти эту проблему, следует использовать ключевое слово with. Оно создаёт менеджер контекста для блока, который оно оборачивает, что гарантирует освобождение ресурсов файла:
with open("/usr/share/dict/words") as f: text = f.read()
Скопировать файл путем чтения и записи
Различные библиотеки Python предоставляют способы копирования файла, поэтому этот пример носит исключительно иллюстративный характер. Он демонстрирует использование второго аргумента функции open, mode. Этот аргумент указывает, как вы собираетесь использовать файл. Вы можете использовать любое допустимое сочетание этих символов:
|
Персонаж |
Значение |
|---|---|
|
р |
Читать |
|
w |
Написать |
|
x |
Создать и написать |
|
а |
Добавить |
|
б |
Двоичный |
|
т |
Текст |
|
+ |
Обновить |
Режим по умолчанию — rt (читать текстовый файл), поэтому первый пример в этой статье сработал так, как вы ожидали. Чтобы скопировать файл, из которого вы читаете, вам нужно открыть второй файл в режиме w для записи. Также необходимо использовать режим b для обоих файлов, чтобы операции чтения и записи корректно обрабатывали бинарные данные.
source = "./image.jpg" target = "./a-copy-of-image.jpg" with open(source, "rb") as src, open(target, "wb") as tgt: buffer = src.read() tgt.write(buffer)
Блок with работает с обоими файлами, поэтому он автоматически закроет их после завершения.
В то время как функция open в Python предоставляет низкоуровневый доступ к содержимому файла, модуль os предоставляет множество более высокоуровневых функций, которые работают с файлами и файловой системой.
Создать новый текстовый файл
Вы также можете использовать аргумент mode для создания нового файла, но защитите любой файл с таким же именем, который уже может существовать:
open(filename, "x")
Если файл с таким именем уже существует, этот вызов open вызовет исключение FileExistsError. Это хорошая защитная мера, которая позволяет избежать необходимости явной проверки существования файла:
# Warning: don't do this! import os.path filename = "example.txt" if os.path.isfile(filename): print("Sorry, file already exists") else: with open(filename, "w") as f: # ...
Кроме того, что приходится писать немного меньше кода, есть ещё более веская причина использовать режим «x»: он предотвращает состояние гонки. Рассмотрим приведённый выше пример, в котором одна команда проверяет, существует ли файл (if os.path.isfile(filename)), а затем другая открывает его для записи (with open(filename, «w») as f). Если другой процесс будет работать с этим файлом между выполнением этих двух команд, может произойти катастрофа.
Открытие файла в режиме создания может предотвратить катастрофу, потому что одна команда отвечает за проверку файла и его открытие. Либо она не сработает, и существующий файл будет защищён, либо она сработает, и ни один другой процесс в это время не сможет создать файл с таким же именем.
Записывать в журнал, добавляя данные
По умолчанию файл, который вы открываете в режиме записи, сначала будет усечен, поэтому его содержимое будет перезаписано. Чтобы вместо этого добавлять данные в файл, можно использовать режим добавления:
log = open("file.log", "a")
Опять же, ведение журналов в Python лучше осуществлять с помощью модуля logging, который заботится о многих неудобных деталях. Однако, в качестве примера, вы можете записывать логи в файл с помощью кода, подобного этому:
def startup(): print("Just a dummy") def main(): print("Doing the main thing") return 42 def log(msg): logfile.write(msg + "n") logfile = open("file.log", "w") log("starting startup") startup() log("startup finished") log("starting main") ret = main() log("main finished: " + str(ret)) logfile.close()
Используйте буферизацию для управления сохранением файлов
Чтобы избежать постоянного открытия и сохранения одного и того же файла, пример ведения журнала использует глобальную переменную и длительно существующий файловый дескриптор. В простом примере это кажется приемлемым, но в реальной ситуации ваша программа может работать бесконечно, и вы можете захотеть проверить файл журнала в любой момент. Если вы это сделаете, вы можете быть удивлены:
while True: log(random.random()) input("Press Enter to continue")
Этот код имитирует периодическое ведение журнала долгоживущего процесса. Вы можете управлять его записью в журнал, нажимая Enter, когда хотите, чтобы была записана новая строка. Однако, если вы его запустите, вы заметите серьёзный недостаток: если нажать Enter несколько раз и проверить файл журнала, вы увидите, что в него ничего не записывается!
Команда tail — в частности, tail -f — может помочь вам отслеживать изменения в лог-файле в реальном времени.
Если вы нажмёте Enter достаточно раз, вы, наконец, должны увидеть некоторые результаты, поскольку вывод превысит размер буфера по умолчанию в Python. В моей системе это 8192 байта, и на их накопление уйдёт много времени.
К счастью, для таких случаев существует аргумент буферизации, который позволяет задать политику буферизации. В случае с лог-файлом отличным подходом является построчная буферизация, которая
Попробуйте запустить предыдущий пример с небольшой корректировкой:
logfile = open("file.log", "w", 1)
Третий аргумент, 1, указывает на построчную буферизацию. При включении этой опции вы должны увидеть, что файл журнала обновляется каждый раз при выполнении функции log(), потому что она записывает в файл завершающий символ новой строки.
Укажите кодировку для корректной поддержки UTF-8
Кодировка символов — сложная тема, но доминирование UTF-8 в наше время означает, что вам редко придется о ней заботиться. Однако некоторые устаревшие системы могут использовать другие кодировки, и невозможно предсказать, что может появиться в будущем. Ошибки с кодировкой могут вызвать серьезные проблемы.
UTF-16 является альтернативой UTF-8 и более эффективен для определенных типов текста. Большинство текстов на английском языке лучше подходит для UTF-8, но текст на других языках или наборы символов — например, файл, полный эмодзи — будут занимать меньше места, если их хранить в формате UTF-16.
Если вы попытаетесь открыть файл UTF-16 с помощью стандартного метода открытия, вы получите ошибку:
Функция open — с некоторыми оговорками — по умолчанию ожидает кодировку UTF-8, поэтому для открытия файла в формате UTF-16 нужно указать соответствующую кодировку:
f = open("../utf16-file.txt", encoding="utf-16")
Используя именованный аргумент, вы можете оставить аргументы mode и buffering по умолчанию. В качестве альтернативы, вы можете задать для них значения по умолчанию (или свои собственные):
f = open("../utf16-file.txt", "r", -1, "utf-16")
Даже если вы открываете файл в формате UTF-8, рекомендуется явно указать кодировку с помощью этого аргумента. Некоторые операционные системы (например, Windows) могут использовать кодировку, отличную от UTF-8, поэтому не стоит полагаться на настройку по умолчанию.
Обрабатывать неправильно сформированные файлы с помощью параметра Errors
Хотя следует позаботиться о указании кодировки, это не всегда возможно. Но функция open не обязательно должна выдавать ошибку при проблемах с кодировкой; вы можете использовать аргумент errors, чтобы выбрать ее поведение из нескольких вариантов.
Значение по умолчанию — ‘strict’, которое вызывает исключение, но вы можете полностью игнорировать такие ошибки с помощью ‘ignore’:
f = open("../utf16-file.txt", errors='ignore')
Недостаток заключается в том, что вы теперь можете иметь дело с повреждёнными данными, не зная об этом. Будете ли вы в состоянии справиться с этим, зависит от характера ваших данных.
Распространённой альтернативой является замена недопустимых символов символом, указывающим на их отсутствие, обычно знаком вопроса. Вы могли заметить такое поведение на отдельных веб-страницах, где кодировка не была указана правильно. Значение ‘replace’ для аргумента errors делает именно это.
Наконец, значение ‘backslashreplace’ заменит каждый повреждённый символ на его эквивалент в виде последовательности с обратной косой чертой в Python. Это может помочь вам определить исходную причину проблемы, поэтому может быть полезно для тестирования или как часть набора инструментов разработчика.




Добавить комментарий