У меня есть следующий скрипт Python 3:
from sys import argv
script, filename = argv
txt = open(filename)
print(f"Here's your file {filename}:")
print(txt.read())
Когда мы используем встроенную функцию open()
, мы открываем файл и возвращаем соответствующий файловый объект.
Я так понимаю read()
это не встроенная функция, а метод файлового объекта.
Как указано здесь в документах Python о файловых объектах https://docs.python.org/3/glossary.html#term-file-object:
There are actually three categories of file objects: raw binary files, buffered binary files and text files. Their interfaces are defined in the io module.
Я действительно изо всех сил пытаюсь понять несколько ключевых областей.
1) Как узнать, с каким типом файлового объекта я буду работать: с необработанными двоичными, буферизованными двоичными и текстовыми файлами? В этом примере я использую простой файл .txt, поэтому я предполагаю, что файловый объект будет текстовым файлом.
2) Как узнать, какой конкретный метод read()
я вызываю, когда использую модуль io? Частью какого класса он является, так как несколько классов имеют доступный метод чтения
Пожалуйста, отвечайте как можно проще, так как я новичок в Python. Я просто не очень хорошо понимаю документацию по модулю io. Я быстро теряюсь, начиная с шага 3, и мне нужно объяснить это простыми шагами.
Я прилагаю все усилия, чтобы понять логические шаги по навигации по документации, поэтому, пожалуйста, измените эти шаги по мере необходимости.
Мое понимание заключается в следующем:
open()
io
для работы с файловым объектом.TextIOBase
.io.TextIOBase
, в котором доступны различные методы, такие как read()
.Кстати: open находится в реальной фабричной функции, она просто гарантирует, что возвращаемый объект будет иметь обещанный интерфейс. Посмотрите это видео youtu.be/rAZBK7jE7b8?t=1406
Есть определенные вещи, которые идентичны между любым файловым объектом, и вы можете видеть это в файле иерархия классов. Все файловые объекты имеют IOBase
в качестве базового класса, который определяет вещи, общие для всех файловых объектов. Затем он специализируется на классах RawIOBase
, BufferedIOBase
и TextIOBase
, которые затем специализируются на FileIO
и BytesIO
и еще много чего. Это типичная иерархия классов ООП.
Их всех объединяет то, что все они определяют метод read
. То, что делает этот метод, немного отличается в деталях, но общая функция одна и та же: он считывает любые базовые данные и возвращает эти данные. Это типичная абстракция/инкапсуляция/полиморфизм ООП: вам не нужно заботиться о том, как он это делает или что именно он делает, вам просто нужно знать, что вы вызываете .read()
для получения данных.
Вы можете создавать экземпляры этих классов по отдельности, но обычно вы используете open
, чтобы упростить эту потенциально сложную задачу. open
решает, какой класс вернуть вам, основываясь на том, что именно вы запросили:
Text I/O
Text I/O expects and produces
str
objects. This means that whenever the backing store is natively made of bytes (such as in the case of a file), encoding and decoding of data is made transparently as well as optional translation of platform-specific newline characters.The easiest way to create a text stream is with
open()
, optionally specifying an encoding:f = open("myfile.txt", "r", encoding = "utf-8")
Binary I/O
Binary I/O (also called buffered I/O) expects
bytes
-like objects and producesbytes
objects. No encoding, decoding, or newline translation is performed. [...]The easiest way to create a binary stream is with
open()
with'b'
in themode
string:f = open("myfile.jpg", "rb")
Raw I/O
Raw I/O (also called unbuffered I/O) is generally used as a low-level building-block for binary and text streams; it is rarely useful to directly manipulate a raw stream from user code. Nevertheless, you can create a raw stream by opening a file in binary mode with
buffering
disabled:f = open("myfile.jpg", "rb", buffering=0)
Все дело в том, как вы открываете файл.
Если вы вызовете open(path)
, вы откроете path
как объект текстового файла. Если вы вызовете open(path, 'rb')
, вы откроете его как буферизованный двоичный файл. Если вы вызовете open(path, 'rb', buffering=0)
, вы откроете его как небуферизованный двоичный файл. Просто так =)
Пожалуйста, обратитесь к https://docs.python.org/3/library/io.html для получения дополнительной информации.
How do I know which file object type I will be working with of raw binary, buffered binary and text files? In this example I am using a simple .txt file, so I would assume the file object would be a text file.
Вы не знаете. Но есть способы определить/угадать тип содержимого файла, очень похожие на команду Linux file
. Например, взгляните на пакет магия питона:
import magic
m = magic.Magic(mime=True)
print(m.from_file(filename))
Это даст вам MIME-тип файла, например. application/json
и тогда бы вы знали, читать его как текстовый или бинарный файл.
Читаете ли вы текстовый или двоичный файл в буфере или нет, зависит от того, как вы его открываете, см. также модуль ио.
В других ответах содержится более подробная информация о IO, поэтому я не буду вдаваться в подробности здесь… ?
In this example I am using a simple .txt file, so I would assume the file object would be a text file."
Это совершенно не связано.
Расширение является лишь соглашением об именах. Это не имеет абсолютно никакого отношения к эффективному контенту, который с чисто технической точки зрения всегда состоит из байтов (разница в том, как вы интерпретируете эти байты), и это не имеет никакого отношения к тому, какой класс ввода-вывода open()
будет использовать либо , см. полный и отличный ответ Deceze.
Вы также можете прочитать документы модуля
io
, где объясняется разница между типами двоичных файлов.