io --- Các công cụ cốt lõi để làm việc với luồng

Source code: Lib/io.py


Tổng quan

Mô-đun io cung cấp các phương tiện chính của Python để xử lý nhiều loại I/O khác nhau. Có ba loại I/O chính: text I/O, binary I/Oraw I/O. Đây là những danh mục chung và có thể sử dụng nhiều kho lưu trữ hỗ trợ khác nhau cho từng danh mục. Một đối tượng cụ thể thuộc bất kỳ loại nào trong số này được gọi là file object. Các thuật ngữ phổ biến khác là streamfile-like object.

Không phụ thuộc vào danh mục của nó, mỗi đối tượng luồng cụ thể cũng sẽ có nhiều khả năng khác nhau: nó có thể ở chế độ chỉ đọc, chỉ ghi hoặc đọc-ghi. Nó cũng có thể cho phép truy cập ngẫu nhiên tùy ý (tìm kiếm tiến hoặc lùi tới bất kỳ vị trí nào) hoặc chỉ truy cập tuần tự (ví dụ trong trường hợp ổ cắm hoặc đường ống).

Tất cả các luồng đều cẩn thận về loại dữ liệu bạn cung cấp cho chúng. Ví dụ: đưa đối tượng str vào phương thức write() của luồng nhị phân sẽ tạo ra TypeError. Vì vậy, việc cung cấp đối tượng bytes cho phương thức write() của luồng văn bản cũng vậy.

Thay đổi trong phiên bản 3.3: Các hoạt động trước đây tăng IOError giờ đây tăng OSError, vì IOError hiện là bí danh của OSError.

Vào/ra văn bản

I/O văn bản mong đợi và tạo ra các đối tượng str. Điều này có nghĩa là bất cứ khi nào kho dự phòng được tạo từ byte (chẳng hạn như trong trường hợp tệp), việc mã hóa và giải mã dữ liệu được thực hiện một cách minh bạch cũng như việc dịch tùy chọn các ký tự dòng mới dành riêng cho nền tảng.

Cách dễ nhất để tạo luồng văn bản là sử dụng open(), tùy ý chỉ định mã hóa:

f = open("myfile.txt", "r",  hóa="utf-8")

Các luồng văn bản trong bộ nhớ cũng có sẵn dưới dạng đối tượng StringIO:

f = io.StringIO("một số dữ liệu văn bản ban đầu")

Ghi chú

Khi làm việc với luồng không chặn, hãy lưu ý rằng các thao tác đọc trên đối tượng I/O văn bản có thể tăng BlockingIOError nếu luồng không thể thực hiện thao tác ngay lập tức.

Luồng văn bản API được mô tả chi tiết trong tài liệu của TextIOBase.

I/O nhị phân

I/O nhị phân (còn gọi là buffered I/O) mong đợi bytes-like objects và tạo ra các đối tượng bytes. Không thực hiện mã hóa, giải mã hoặc dịch dòng mới. Loại luồng này có thể được sử dụng cho tất cả các loại dữ liệu phi văn bản và cả khi muốn kiểm soát thủ công việc xử lý dữ liệu văn bản.

Cách dễ nhất để tạo luồng nhị phân là với open() với 'b' trong chuỗi chế độ

f = open("myfile.jpg", "rb")

Luồng nhị phân trong bộ nhớ cũng có sẵn dưới dạng đối tượng BytesIO

f = io.BytesIO(b"một số dữ liệu nhị phân ban đầu: \x00\x01")

Luồng nhị phân API được mô tả chi tiết trong tài liệu của BufferedIOBase.

Các mô-đun thư viện khác có thể cung cấp các cách bổ sung để tạo văn bản hoặc luồng nhị phân. Xem socket.socket.makefile() chẳng hạn.

I/O thô

I/O thô (còn được gọi là unbuffered I/O) thường được sử dụng làm khối xây dựng cấp thấp cho các luồng văn bản và nhị phân; việc thao tác trực tiếp luồng thô từ mã người dùng hiếm khi hữu ích. Tuy nhiên, bạn có thể tạo luồng thô bằng cách mở tệp ở chế độ nhị phân với tính năng đệm bị tắt

f = open("myfile.jpg", "rb", đệm=0)

Luồng thô API được mô tả chi tiết trong tài liệu của RawIOBase.

Mã hóa văn bản

Mã hóa mặc định của TextIOWrapperopen() là dành riêng cho miền địa phương (locale.getencoding()).

Tuy nhiên, nhiều nhà phát triển quên chỉ định mã hóa khi mở tệp văn bản được mã hóa bằng UTF-8 (ví dụ: JSON, TOML, Markdown, v.v.) vì hầu hết các nền tảng Unix đều sử dụng ngôn ngữ UTF-8 theo mặc định. Điều này gây ra lỗi vì mã hóa ngôn ngữ không phải là UTF-8 đối với hầu hết người dùng Windows. Ví dụ:

# May không hoạt động trên Windows khi có các ký tự không phải ASCII trong tệp.
với open("README.md")  f:
    long_description = f.read()

Theo đó, bạn nên chỉ định rõ ràng mã hóa khi mở tệp văn bản. Nếu bạn muốn sử dụng UTF-8, hãy chuyển encoding="utf-8". Để sử dụng mã hóa ngôn ngữ hiện tại, encoding="locale" được hỗ trợ kể từ Python 3.10.

Xem thêm

Chế độ Python UTF-8

Chế độ UTF-8 của Python có thể được sử dụng để thay đổi mã hóa mặc định thành UTF-8 từ mã hóa theo ngôn ngữ cụ thể.

PEP 686

Python 3.15 sẽ đặt Chế độ Python UTF-8 làm mặc định.

Cảnh báo mã hóa chọn tham gia

Added in version 3.10: Xem PEP 597 để biết thêm chi tiết.

Để tìm nơi sử dụng mã hóa ngôn ngữ mặc định, bạn có thể bật tùy chọn dòng lệnh -X warn_default_encoding hoặc đặt biến môi trường PYTHONWARNDEFAULTENCODING, biến này sẽ phát ra EncodingWarning khi sử dụng mã hóa mặc định.

Nếu bạn đang cung cấp API sử dụng open() hoặc TextIOWrapper và chuyển encoding=None làm tham số, bạn có thể sử dụng text_encoding() để người gọi API sẽ phát ra EncodingWarning nếu họ không chuyển encoding. Tuy nhiên, vui lòng cân nhắc sử dụng UTF-8 theo mặc định (tức là encoding="utf-8") cho các API mới.

Giao diện mô-đun cấp cao

io.DEFAULT_BUFFER_SIZE

Một int chứa kích thước bộ đệm mặc định được sử dụng bởi các lớp I/O được đệm của mô-đun. open() sử dụng blksize của tệp (do os.stat() thu được) nếu có thể.

io.open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

Đây là bí danh cho hàm open() dựng sẵn.

Hàm này tạo ra một auditing event open với các đối số path, modeflags. Các đối số modeflags có thể đã được sửa đổi hoặc suy ra từ lệnh gọi ban đầu.

io.open_code(path)

Mở tệp được cung cấp với chế độ 'rb'. Hàm này nên được sử dụng khi mục đích coi nội dung là mã thực thi.

path phải là str và là đường dẫn tuyệt đối.

Hoạt động của chức năng này có thể bị ghi đè bằng lệnh gọi trước đó tới PyFile_SetOpenCodeHook(). Tuy nhiên, giả sử rằng pathstr và là đường dẫn tuyệt đối, open_code(path) sẽ luôn hoạt động giống như open(path, 'rb'). Việc ghi đè hành vi nhằm mục đích xác thực bổ sung hoặc xử lý trước tệp.

Added in version 3.8.

io.text_encoding(encoding, stacklevel=2, /)

Đây là hàm trợ giúp dành cho các lệnh gọi sử dụng open() hoặc TextIOWrapper và có tham số encoding=None.

Hàm này trả về encoding nếu nó không phải là None. Ngược lại, nó trả về "locale" hoặc "utf-8" tùy thuộc vào UTF-8 Mode.

Hàm này phát ra EncodingWarning nếu sys.flags.warn_default_encoding là đúng và encodingNone. stacklevel chỉ định nơi phát ra cảnh báo. Ví dụ:

def read_text(đường dẫn,  hóa=Không):
     hóa = io.text_encoding( hóa) # stacklevel=2
    với open(path, Encoding)  f:
        trả về f.read()

Trong ví dụ này, một EncodingWarning được phát ra cho người gọi read_text().

Xem Mã hóa văn bản để biết thêm thông tin.

Added in version 3.10.

Thay đổi trong phiên bản 3.11: text_encoding() trả về "utf-8" khi chế độ UTF-8 được bật và encodingNone.

exception io.BlockingIOError

Đây là bí danh tương thích cho ngoại lệ BlockingIOError dựng sẵn.

exception io.UnsupportedOperation

Một ngoại lệ kế thừa OSErrorValueError được đưa ra khi một thao tác không được hỗ trợ được gọi trên luồng.

Xem thêm

sys

chứa các luồng IO tiêu chuẩn: sys.stdin, sys.stdoutsys.stderr.

Hệ thống phân cấp lớp

Việc triển khai các luồng I/O được tổ chức dưới dạng phân cấp các lớp. Đầu tiên là abstract base classes (ABC), được sử dụng để chỉ định các loại luồng khác nhau, sau đó là các lớp cụ thể cung cấp cách triển khai luồng tiêu chuẩn.

Ghi chú

Các lớp cơ sở trừu tượng cũng cung cấp cách triển khai mặc định của một số phương thức để giúp triển khai các lớp luồng cụ thể. Ví dụ: BufferedIOBase cung cấp các triển khai chưa được tối ưu hóa của readinto()readline().

Ở trên cùng của hệ thống phân cấp I/O là lớp cơ sở trừu tượng IOBase. Nó xác định giao diện cơ bản cho một luồng. Tuy nhiên, hãy lưu ý rằng không có sự tách biệt giữa việc đọc và ghi vào luồng; việc triển khai được phép tăng UnsupportedOperation nếu chúng không hỗ trợ một thao tác nhất định.

RawIOBase ABC mở rộng IOBase. Nó xử lý việc đọc và ghi byte vào một luồng. FileIO phân lớp RawIOBase để cung cấp giao diện cho các tệp trong hệ thống tệp của máy.

BufferedIOBase ABC mở rộng IOBase. Nó xử lý việc đệm trên luồng nhị phân thô (RawIOBase). Các lớp con của nó, BufferedWriter, BufferedReaderBufferedRWPair đệm các luồng nhị phân thô tương ứng có thể ghi, có thể đọc và cả hai đều có thể đọc và ghi. BufferedRandom cung cấp giao diện được đệm cho các luồng có thể tìm kiếm. Một lớp con BufferedIOBase khác, BytesIO, là một luồng byte trong bộ nhớ.

TextIOBase ABC mở rộng IOBase. Nó xử lý các luồng có byte đại diện cho văn bản và xử lý mã hóa và giải mã đến và đi từ các chuỗi. TextIOWrapper, mở rộng TextIOBase, là giao diện văn bản được lưu vào bộ đệm cho luồng thô được lưu vào bộ đệm (BufferedIOBase). Cuối cùng, StringIO là luồng văn bản trong bộ nhớ.

Tên đối số không phải là một phần của đặc tả và chỉ các đối số của open() mới được sử dụng làm đối số từ khóa.

Bảng sau đây tóm tắt các ABC do mô-đun io cung cấp:

ABC

Kế thừa

Phương pháp sơ khai

Phương pháp và thuộc tính Mixin

IOBase

fileno, seektruncate

close, closed, __enter__, __exit__, flush, isatty, __iter__, __next__, readable, readline, readlines, seekable, tell, writable, và writelines

RawIOBase

IOBase

readintowrite

Kế thừa các phương thức IOBase, readreadall

BufferedIOBase

IOBase

detach, read, read1write

Kế thừa các phương thức IOBase, readintoreadinto1

TextIOBase

IOBase

detach, read, readlinewrite

Kế thừa các phương thức IOBase, encoding, errorsnewlines

Các lớp cơ sở I/O

class io.IOBase

Lớp cơ sở trừu tượng cho tất cả các lớp I/O.

Lớp này cung cấp các triển khai trừu tượng trống cho nhiều phương thức mà các lớp dẫn xuất có thể ghi đè một cách có chọn lọc; việc triển khai mặc định đại diện cho một tệp không thể đọc, ghi hoặc tìm kiếm.

Mặc dù IOBase không khai báo read() hoặc write() vì chữ ký của chúng sẽ khác nhau, nhưng việc triển khai và khách hàng nên coi các phương thức đó là một phần của giao diện. Ngoài ra, việc triển khai có thể tạo ra ValueError (hoặc UnsupportedOperation) khi các hoạt động mà chúng không hỗ trợ được gọi.

Loại cơ bản được sử dụng để đọc hoặc ghi dữ liệu nhị phân vào tệp là bytes. bytes-like objects khác cũng được chấp nhận làm đối số phương thức. Các lớp I/O văn bản hoạt động với dữ liệu str.

Lưu ý rằng việc gọi bất kỳ phương thức nào (thậm chí cả yêu cầu) trên luồng đã đóng đều không được xác định. Việc triển khai có thể tăng ValueError trong trường hợp này.

IOBase (và các lớp con của nó) hỗ trợ giao thức iterator, nghĩa là một đối tượng IOBase có thể được lặp lại để tạo ra các dòng trong luồng. Các dòng được xác định hơi khác nhau tùy thuộc vào việc luồng đó là luồng nhị phân (mang lại byte) hay luồng văn bản (mang lại chuỗi ký tự). Xem readline() bên dưới.

IOBase cũng là một trình quản lý bối cảnh và do đó hỗ trợ câu lệnh with. Trong ví dụ này, file bị đóng sau khi bộ câu lệnh with kết thúc---ngay cả khi xảy ra ngoại lệ:

với open('spam.txt', 'w') dưới dạng tệp:
    file.write('Spam và trứng!')

IOBase cung cấp các thuộc tính và phương thức dữ liệu sau:

close()

Xóa và đóng luồng này. Phương pháp này không có hiệu lực nếu tệp đã bị đóng. Khi tệp được đóng, mọi thao tác trên tệp (ví dụ: đọc hoặc ghi) sẽ tạo ra ValueError.

Để thuận tiện, nó được phép gọi phương thức này nhiều lần; Tuy nhiên, chỉ cuộc gọi đầu tiên mới có hiệu lực.

closed

True nếu luồng bị đóng.

fileno()

Trả về bộ mô tả tệp cơ bản (số nguyên) của luồng nếu nó tồn tại. Một OSError được nâng lên nếu đối tượng IO không sử dụng bộ mô tả tệp.

flush()

Xóa bộ đệm ghi của luồng nếu có. Điều này không có tác dụng gì đối với các luồng chỉ đọc và không chặn.

isatty()

Trả về True nếu luồng có tính tương tác (tức là được kết nối với thiết bị đầu cuối/tty).

readable()

Trả về True nếu luồng có thể được đọc từ đó. Nếu False thì read() sẽ raise OSError.

readline(size=-1, /)

Đọc và trả về một dòng từ luồng. Nếu size được chỉ định, tối đa size byte sẽ được đọc.

Bộ kết thúc dòng luôn là b'\n' đối với các tệp nhị phân; đối với các tệp văn bản, đối số newline cho open() có thể được sử dụng để chọn (các) dấu kết thúc dòng được nhận dạng.

readlines(hint=-1, /)

Đọc và trả về danh sách các dòng từ luồng. hint có thể được chỉ định để kiểm soát số dòng được đọc: sẽ không đọc thêm dòng nào nếu tổng kích thước (tính bằng byte/ký tự) của tất cả các dòng cho đến nay vượt quá hint.

Các giá trị hint từ 0 trở xuống, cũng như None, được coi là không có gợi ý.

Lưu ý rằng bạn có thể lặp lại các đối tượng tệp bằng cách sử dụng for line in file: ... mà không cần gọi file.readlines().

seek(offset, whence=os.SEEK_SET, /)

Thay đổi vị trí luồng thành byte offset đã cho, được diễn giải tương ứng với vị trí được chỉ định bởi whence và trả về vị trí tuyệt đối mới. Các giá trị cho whence là:

  • os.SEEK_SET hoặc 0 -- bắt đầu luồng (mặc định); offset phải bằng 0 hoặc dương

  • os.SEEK_CUR hoặc 1 -- vị trí luồng hiện tại; offset có thể âm tính

  • os.SEEK_END hoặc 2 -- kết thúc luồng; offset thường âm tính

Added in version 3.1: Các hằng số SEEK_*.

Added in version 3.3: Một số hệ điều hành có thể hỗ trợ các giá trị bổ sung, như os.SEEK_HOLE hoặc os.SEEK_DATA. Các giá trị hợp lệ cho một tệp có thể phụ thuộc vào việc tệp đó được mở ở chế độ văn bản hoặc nhị phân.

seekable()

Trả về True nếu luồng hỗ trợ truy cập ngẫu nhiên. Nếu False, seek(), tell()truncate() sẽ tăng OSError.

tell()

Trả về vị trí luồng hiện tại.

truncate(size=None, /)

Thay đổi kích thước luồng thành size đã cho theo byte (hoặc vị trí hiện tại nếu size không được chỉ định). Vị trí luồng hiện tại không thay đổi. Việc thay đổi kích thước này có thể mở rộng hoặc giảm kích thước tệp hiện tại. Trong trường hợp mở rộng, nội dung của vùng tệp mới phụ thuộc vào nền tảng (trên hầu hết các hệ thống, các byte bổ sung được điền bằng 0). Kích thước tập tin mới được trả về.

Thay đổi trong phiên bản 3.5: Bây giờ Windows sẽ không điền các tệp khi mở rộng.

writable()

Trả về True nếu luồng hỗ trợ ghi. Nếu False, write()truncate() sẽ tăng OSError.

writelines(lines, /)

Viết danh sách các dòng vào luồng. Dấu phân cách dòng không được thêm vào, do đó, thông thường mỗi dòng được cung cấp sẽ có dấu phân cách dòng ở cuối.

__del__()

Chuẩn bị cho việc phá hủy đối tượng. IOBase cung cấp cách triển khai mặc định của phương thức này gọi phương thức close() của cá thể.

class io.RawIOBase

Lớp cơ sở cho luồng nhị phân thô. Nó kế thừa từ IOBase.

Luồng nhị phân thô thường cung cấp quyền truy cập cấp thấp vào thiết bị hệ điều hành cơ bản hoặc API và không cố gắng đóng gói nó trong các luồng nhị phân cấp cao (chức năng này được thực hiện ở cấp cao hơn trong luồng nhị phân và luồng văn bản được đệm, được mô tả sau trong trang này).

RawIOBase cung cấp các phương thức này ngoài các phương thức từ IOBase:

read(size=-1, /)

Đọc tối đa size byte từ đối tượng và trả về chúng. Để thuận tiện, nếu size không được chỉ định hoặc -1, tất cả byte cho đến EOF sẽ được trả về. Nếu không, chỉ có một cuộc gọi hệ thống được thực hiện. Có thể trả về ít hơn size byte nếu lệnh gọi hệ điều hành trả về ít hơn size byte.

Nếu trả về 0 byte và size không bằng 0, điều này cho biết kết thúc tệp. Nếu đối tượng ở chế độ không chặn và không có byte nào, None sẽ được trả về.

Việc triển khai mặc định trì hoãn readall()readinto().

readall()

Đọc và trả về tất cả byte từ luồng cho đến EOF, sử dụng nhiều lệnh gọi tới luồng nếu cần.

readinto(b, /)

Đọc byte vào một bytes-like object b được phân bổ trước, có thể ghi và trả về số byte đã đọc. Ví dụ: b có thể là bytearray. Nếu đối tượng ở chế độ không chặn và không có byte nào, None sẽ được trả về.

write(b, /)

Viết bytes-like object, b đã cho vào luồng thô bên dưới và trả về số byte đã ghi. Độ dài này có thể nhỏ hơn độ dài của b tính bằng byte, tùy thuộc vào thông tin cụ thể của luồng thô cơ bản và đặc biệt nếu luồng đó ở chế độ không chặn. None được trả về nếu luồng thô được đặt ở chế độ không chặn và không có byte đơn nào có thể được ghi vào luồng đó. Người gọi có thể giải phóng hoặc thay đổi b sau khi phương thức này trả về, vì vậy việc triển khai chỉ nên truy cập b trong khi gọi phương thức.

class io.BufferedIOBase

Lớp cơ sở cho các luồng nhị phân hỗ trợ một số loại đệm. Nó kế thừa từ IOBase.

Sự khác biệt chính với RawIOBase là các phương thức read(), readinto()write() sẽ cố gắng (tương ứng) đọc nhiều dữ liệu đầu vào theo yêu cầu hoặc phát ra tất cả dữ liệu được cung cấp.

Ngoài ra, nếu luồng thô cơ bản ở chế độ không chặn, khi hệ thống quay trở lại, khối write() sẽ tăng BlockingIOError với BlockingIOError.characters_writtenread() sẽ trả về dữ liệu đã đọc cho đến nay hoặc None nếu không có dữ liệu.

Ngoài ra, phương thức read() không có cách triển khai mặc định dành cho readinto().

Việc triển khai BufferedIOBase điển hình không nên kế thừa từ việc triển khai RawIOBase mà nên gói gọn một triển khai, giống như BufferedWriterBufferedReader.

BufferedIOBase cung cấp hoặc ghi đè các thuộc tính và phương thức dữ liệu này ngoài các thuộc tính và phương thức dữ liệu từ IOBase:

raw

Luồng thô cơ bản (phiên bản RawIOBase) mà BufferedIOBase xử lý. Đây không phải là một phần của BufferedIOBase API và có thể không tồn tại trên một số triển khai.

detach()

Tách luồng thô cơ bản khỏi bộ đệm và trả lại nó.

Sau khi luồng thô bị tách ra, bộ đệm ở trạng thái không sử dụng được.

Một số bộ đệm, như BytesIO, không có khái niệm về một luồng thô duy nhất được trả về từ phương thức này. Họ quyên góp UnsupportedOperation.

Added in version 3.1.

read(size=-1, /)

Đọc và trả về byte size. Nếu đối số bị bỏ qua, None hoặc đọc âm càng nhiều càng tốt.

Có thể trả về ít byte hơn yêu cầu. Một đối tượng bytes trống sẽ được trả về nếu luồng đã ở EOF. Có thể thực hiện nhiều lần đọc và thử lại các lệnh gọi nếu gặp phải lỗi cụ thể, hãy xem os.read()PEP 475 để biết thêm chi tiết. Kích thước byte nhỏ hơn được trả về không có nghĩa là EOF sắp xảy ra.

Khi đọc càng nhiều càng tốt, việc triển khai mặc định sẽ sử dụng raw.readall nếu có (cần triển khai RawIOBase.readall()), nếu không thì sẽ đọc theo vòng lặp cho đến khi đọc trả về None, bytes trống hoặc lỗi không thể thử lại. Đối với hầu hết các luồng, đây là EOF, nhưng đối với các luồng không chặn, có thể có nhiều dữ liệu hơn.

Ghi chú

Khi luồng thô cơ bản không bị chặn, việc triển khai có thể tăng BlockingIOError hoặc trả về None nếu không có dữ liệu. Việc triển khai io trả về None.

read1(size=-1, /)

Đọc và trả về tối đa size byte, gọi readinto() có thể thử lại nếu gặp EINTR trên mỗi PEP 475. Nếu size-1 hoặc không được cung cấp, quá trình triển khai sẽ chọn một giá trị tùy ý cho size.

Ghi chú

Khi luồng thô cơ bản không bị chặn, việc triển khai có thể tăng BlockingIOError hoặc trả về None nếu không có dữ liệu. Việc triển khai io trả về None.

readinto(b, /)

Đọc byte vào một bytes-like object b được phân bổ trước, có thể ghi và trả về số byte đã đọc. Ví dụ: b có thể là bytearray.

Giống như read(), nhiều lần đọc có thể được cấp cho luồng thô cơ bản, trừ khi luồng sau có tính tương tác.

Một BlockingIOError được tăng lên nếu luồng thô cơ bản ở chế độ không chặn và hiện không có sẵn dữ liệu.

readinto1(b, /)

Đọc byte thành một bytes-like object b được phân bổ trước, có thể ghi, sử dụng tối đa một lệnh gọi đến phương thức read() (hoặc readinto()) của luồng thô cơ bản. Trả về số byte đã đọc.

Một BlockingIOError được tăng lên nếu luồng thô cơ bản ở chế độ không chặn và hiện không có sẵn dữ liệu.

Added in version 3.5.

write(b, /)

Viết bytes-like object, b đã cho và trả về số byte đã ghi (luôn bằng độ dài của b tính bằng byte, vì nếu ghi không thành công thì OSError sẽ được tăng lên). Tùy thuộc vào việc triển khai thực tế, các byte này có thể được ghi dễ dàng vào luồng cơ bản hoặc được giữ trong bộ đệm vì lý do hiệu suất và độ trễ.

Khi ở chế độ không chặn, BlockingIOError sẽ được nâng lên nếu dữ liệu cần được ghi vào luồng thô nhưng nó không thể chấp nhận tất cả dữ liệu mà không chặn.

Người gọi có thể giải phóng hoặc thay đổi b sau khi phương thức này trả về, vì vậy việc triển khai chỉ nên truy cập b trong khi gọi phương thức.

Vào/ra tệp thô

class io.FileIO(name, mode='r', closefd=True, opener=None)

Luồng nhị phân thô biểu thị tệp cấp hệ điều hành chứa dữ liệu byte. Nó kế thừa từ RawIOBase.

Zz000zz có thể là một trong hai thứ:

  • một chuỗi ký tự hoặc đối tượng bytes biểu thị đường dẫn đến tệp sẽ được mở. Trong trường hợp này, closefd phải là True (mặc định) nếu không sẽ xảy ra lỗi.

  • một số nguyên biểu thị số lượng bộ mô tả tệp cấp hệ điều hành hiện có mà đối tượng FileIO kết quả sẽ cấp quyền truy cập. Khi đối tượng FileIO bị đóng, fd này cũng sẽ bị đóng, trừ khi closefd được đặt thành False.

Zz007zz có thể là 'r', 'w', 'x' hoặc 'a' để đọc (mặc định), viết, tạo hoặc thêm độc quyền. Tệp sẽ được tạo nếu nó không tồn tại khi mở để ghi hoặc nối thêm; nó sẽ bị cắt bớt khi mở ra để viết. FileExistsError sẽ được nâng lên nếu nó đã tồn tại khi mở để tạo. Việc mở một tệp để tạo có nghĩa là ghi, vì vậy chế độ này hoạt động theo cách tương tự như 'w'. Thêm '+' vào chế độ để cho phép đọc và ghi đồng thời.

Các phương thức read() (khi được gọi với đối số dương), readinto()write() trên lớp này sẽ chỉ thực hiện một lệnh gọi hệ thống.

Bạn có thể sử dụng công cụ mở tùy chỉnh bằng cách chuyển một lệnh gọi có thể gọi là opener. Sau đó, bộ mô tả tệp cơ bản cho đối tượng tệp được lấy bằng cách gọi opener với (name, flags). opener phải trả về một bộ mô tả tệp đang mở (chuyển os.openopener sẽ có chức năng tương tự như truyền None).

Tệp mới được tạo là non-inheritable.

Xem hàm tích hợp open() để biết ví dụ về cách sử dụng tham số opener.

Thay đổi trong phiên bản 3.3: Tham số opener đã được thêm vào. Chế độ 'x' đã được thêm vào.

Thay đổi trong phiên bản 3.4: Các tập tin bây giờ không thể kế thừa.

FileIO cung cấp các thuộc tính dữ liệu này ngoài các thuộc tính dữ liệu từ RawIOBaseIOBase:

mode

Chế độ như được đưa ra trong hàm tạo.

name

Tên tập tin. Đây là bộ mô tả tệp của tệp khi không có tên nào được đưa ra trong hàm tạo.

Luồng đệm

Các luồng I/O được đệm cung cấp giao diện cấp cao hơn cho thiết bị I/O so với I/O thô.

class io.BytesIO(initial_bytes=b'')

Luồng nhị phân sử dụng bộ đệm byte trong bộ nhớ. Nó kế thừa từ BufferedIOBase. Bộ đệm bị loại bỏ khi phương thức close() được gọi.

Đối số tùy chọn initial_bytesbytes-like object chứa dữ liệu ban đầu.

BytesIO cung cấp hoặc ghi đè các phương thức này ngoài các phương thức từ BufferedIOBaseIOBase:

getbuffer()

Trả về chế độ xem có thể đọc và ghi đối với nội dung của bộ đệm mà không cần sao chép chúng. Ngoài ra, việc thay đổi chế độ xem sẽ cập nhật một cách minh bạch nội dung của bộ đệm

>>> b = io.BytesIO(b"abcdef")
>>> view = b.getbuffer()
>>> xem[2:4] = b"56"
>>> b.getvalue()
b'ab56ef'

Ghi chú

Miễn là chế độ xem tồn tại, đối tượng BytesIO không thể thay đổi kích thước hoặc đóng.

Added in version 3.2.

getvalue()

Trả về bytes chứa toàn bộ nội dung của bộ đệm.

read1(size=-1, /)

Trong BytesIO, điều này giống với read().

Thay đổi trong phiên bản 3.7: Đối số size hiện là tùy chọn.

readinto1(b, /)

Trong BytesIO, điều này giống với readinto().

Added in version 3.5.

class io.BufferedReader(raw, buffer_size=DEFAULT_BUFFER_SIZE)

Luồng nhị phân được lưu vào bộ đệm cung cấp quyền truy cập cấp cao hơn vào luồng nhị phân thô RawIOBase có thể đọc được, không thể tìm kiếm được. Nó kế thừa từ BufferedIOBase.

Khi đọc dữ liệu từ đối tượng này, lượng dữ liệu lớn hơn có thể được yêu cầu từ luồng thô cơ bản và được lưu trong bộ đệm bên trong. Dữ liệu được lưu vào bộ đệm sau đó có thể được trả về trực tiếp trong các lần đọc tiếp theo.

Hàm tạo tạo một BufferedReader cho luồng raw có thể đọc được và buffer_size. Nếu buffer_size bị bỏ qua, DEFAULT_BUFFER_SIZE sẽ được sử dụng.

BufferedReader cung cấp hoặc ghi đè các phương thức này ngoài các phương thức từ BufferedIOBaseIOBase:

peek(size=0, /)

Trả về byte từ luồng mà không nâng cao vị trí. Số byte trả về có thể ít hơn hoặc nhiều hơn yêu cầu. Nếu luồng thô cơ bản không bị chặn và thao tác sẽ chặn thì sẽ trả về các byte trống.

read(size=-1, /)

Trong BufferedReader cái này giống với io.BufferedIOBase.read()

read1(size=-1, /)

Trong BufferedReader cái này giống với io.BufferedIOBase.read1()

Thay đổi trong phiên bản 3.7: Đối số size hiện là tùy chọn.

class io.BufferedWriter(raw, buffer_size=DEFAULT_BUFFER_SIZE)

Luồng nhị phân được lưu vào bộ đệm cung cấp quyền truy cập cấp cao hơn vào luồng nhị phân thô RawIOBase có thể ghi, không thể tìm kiếm. Nó kế thừa từ BufferedIOBase.

Khi ghi vào đối tượng này, dữ liệu thường được đặt vào bộ đệm bên trong. Bộ đệm sẽ được ghi vào đối tượng RawIOBase cơ bản trong các điều kiện khác nhau, bao gồm:

  • khi bộ đệm quá nhỏ đối với tất cả dữ liệu đang chờ xử lý;

  • khi flush() được gọi;

  • khi yêu cầu seek() (đối với đối tượng BufferedRandom);

  • khi đối tượng BufferedWriter bị đóng hoặc bị phá hủy.

Hàm tạo tạo một BufferedWriter cho luồng raw có thể ghi được. Nếu buffer_size không được cung cấp, nó sẽ mặc định là DEFAULT_BUFFER_SIZE.

BufferedWriter cung cấp hoặc ghi đè các phương thức này ngoài các phương thức từ BufferedIOBaseIOBase:

flush()

Buộc các byte được giữ trong bộ đệm vào luồng thô. Một BlockingIOError sẽ được tăng lên nếu luồng thô bị chặn.

write(b, /)

Viết bytes-like object, b và trả về số byte đã ghi. Khi ở chế độ không chặn, một bộ BlockingIOError với BlockingIOError.characters_written sẽ được nâng lên nếu bộ đệm cần được ghi ra nhưng luồng thô sẽ chặn.

class io.BufferedRandom(raw, buffer_size=DEFAULT_BUFFER_SIZE)

Luồng nhị phân được lưu vào bộ đệm cung cấp quyền truy cập cấp cao hơn vào luồng nhị phân thô RawIOBase có thể tìm kiếm. Nó kế thừa từ BufferedReaderBufferedWriter.

Hàm tạo tạo một trình đọc và trình ghi cho luồng thô có thể tìm kiếm, được đưa ra trong đối số đầu tiên. Nếu buffer_size bị bỏ qua, nó sẽ mặc định là DEFAULT_BUFFER_SIZE.

BufferedRandom có khả năng làm mọi việc mà BufferedReader hoặc BufferedWriter có thể làm. Ngoài ra, seek()tell() được đảm bảo sẽ được triển khai.

class io.BufferedRWPair(reader, writer, buffer_size=DEFAULT_BUFFER_SIZE, /)

Luồng nhị phân được lưu vào bộ đệm cung cấp quyền truy cập cấp cao hơn vào hai luồng nhị phân thô RawIOBase không thể tìm kiếm---một luồng có thể đọc được, luồng còn lại có thể ghi. Nó kế thừa từ BufferedIOBase.

readerwriter lần lượt là các đối tượng RawIOBase có thể đọc và ghi được. Nếu buffer_size bị bỏ qua, nó sẽ mặc định là DEFAULT_BUFFER_SIZE.

BufferedRWPair thực hiện tất cả các phương thức của BufferedIOBase ngoại trừ detach(), làm tăng UnsupportedOperation.

Cảnh báo

BufferedRWPair không cố gắng đồng bộ hóa quyền truy cập vào luồng thô cơ bản của nó. Bạn không nên truyền cho nó cùng một đối tượng như reader và writer; thay vào đó hãy sử dụng BufferedRandom.

Vào/ra văn bản

class io.TextIOBase

Lớp cơ sở cho luồng văn bản. Lớp này cung cấp giao diện dựa trên ký tự và dòng để truyền phát I/O. Nó kế thừa từ IOBase.

TextIOBase cung cấp hoặc ghi đè các thuộc tính và phương thức dữ liệu này ngoài các thuộc tính và phương thức dữ liệu từ IOBase:

encoding

Tên mã hóa được sử dụng để giải mã byte của luồng thành chuỗi và mã hóa chuỗi thành byte.

errors

Cài đặt lỗi của bộ giải mã hoặc bộ mã hóa.

newlines

Một chuỗi, một bộ chuỗi hoặc None, biểu thị các dòng mới được dịch cho đến nay. Tùy thuộc vào việc triển khai và cờ hàm tạo ban đầu, điều này có thể không khả dụng.

buffer

Bộ đệm nhị phân cơ bản (phiên bản BufferedIOBase hoặc RawIOBase) mà TextIOBase xử lý. Đây không phải là một phần của TextIOBase API và có thể không tồn tại trong một số triển khai.

detach()

Tách bộ đệm nhị phân cơ bản khỏi TextIOBase và trả lại.

Sau khi bộ đệm cơ bản được tách ra, TextIOBase ở trạng thái không sử dụng được.

Một số triển khai TextIOBase, như StringIO, có thể không có khái niệm về bộ đệm cơ bản và việc gọi phương thức này sẽ tăng UnsupportedOperation.

Added in version 3.1.

read(size=-1, /)

Đọc và trả về tối đa các ký tự size từ luồng dưới dạng một str. Nếu size âm hoặc None, hãy đọc cho đến EOF.

readline(size=-1, /)

Đọc cho đến dòng mới hoặc EOF và trả về một str. Nếu luồng đã ở EOF, một chuỗi trống sẽ được trả về.

Nếu size được chỉ định, tối đa size ký tự sẽ được đọc.

seek(offset, whence=SEEK_SET, /)

Thay đổi vị trí luồng thành offset đã cho. Hành vi phụ thuộc vào tham số whence. Giá trị mặc định cho whenceSEEK_SET.

  • SEEK_SET hoặc 0: tìm kiếm từ đầu luồng (mặc định); offset phải là số được trả về bởi TextIOBase.tell() hoặc bằng 0. Bất kỳ giá trị offset nào khác đều tạo ra hành vi không xác định.

  • SEEK_CUR hoặc 1: "tìm kiếm" vị trí hiện tại; offset phải bằng 0, tức là không hoạt động (tất cả các giá trị khác đều không được hỗ trợ).

  • SEEK_END hoặc 2: tìm đến cuối luồng; offset phải bằng 0 (tất cả các giá trị khác không được hỗ trợ).

Trả về vị trí tuyệt đối mới dưới dạng số mờ.

Added in version 3.1: Các hằng số SEEK_*.

tell()

Trả về vị trí luồng hiện tại dưới dạng số mờ. Số này thường không đại diện cho một số byte trong bộ lưu trữ nhị phân cơ bản.

write(s, /)

Viết chuỗi s vào luồng và trả về số ký tự đã ghi.

class io.TextIOWrapper(buffer, encoding=None, errors=None, newline=None, line_buffering=False, write_through=False)

Luồng văn bản được lưu vào bộ đệm cung cấp quyền truy cập cấp cao hơn vào luồng nhị phân được lưu vào bộ đệm BufferedIOBase. Nó kế thừa từ TextIOBase.

encoding cung cấp tên mã hóa mà luồng sẽ được giải mã hoặc mã hóa. Trong UTF-8 Mode, giá trị mặc định là UTF-8. Ngược lại, nó mặc định là locale.getencoding(). encoding="locale" có thể được sử dụng để chỉ định rõ ràng mã hóa của ngôn ngữ hiện tại. Xem Mã hóa văn bản để biết thêm thông tin.

errors là một chuỗi tùy chọn chỉ định cách xử lý các lỗi mã hóa và giải mã. Truyền 'strict' để đưa ra ngoại lệ ValueError nếu có lỗi mã hóa (mặc định là None có tác dụng tương tự) hoặc truyền 'ignore' để bỏ qua lỗi. (Lưu ý rằng việc bỏ qua lỗi mã hóa có thể dẫn đến mất dữ liệu.) 'replace' khiến một điểm đánh dấu thay thế (chẳng hạn như '?') được chèn vào nơi có dữ liệu không đúng định dạng. 'backslashreplace' khiến dữ liệu không đúng định dạng được thay thế bằng chuỗi thoát bị gạch chéo ngược. Khi viết, có thể sử dụng 'xmlcharrefreplace' (thay thế bằng tham chiếu ký tự XML thích hợp) hoặc 'namereplace' (thay thế bằng chuỗi thoát \N{...}). Bất kỳ tên xử lý lỗi nào khác đã được đăng ký với codecs.register_error() cũng hợp lệ.

newline kiểm soát cách xử lý kết thúc dòng. Nó có thể là None, '', '\n', '\r''\r\n'. Nó hoạt động như sau:

  • Khi đọc đầu vào từ luồng, nếu newlineNone thì chế độ universal newlines được bật. Các dòng trong đầu vào có thể kết thúc bằng '\n', '\r' hoặc '\r\n' và những dòng này được dịch sang '\n' trước khi được trả lại cho người gọi. Nếu newline'', chế độ dòng mới phổ quát được bật nhưng phần cuối dòng được trả về cho người gọi chưa được dịch. Nếu newline có bất kỳ giá trị hợp pháp nào khác, các dòng đầu vào chỉ được kết thúc bởi chuỗi đã cho và kết thúc dòng được trả về cho người gọi chưa được dịch.

  • Khi ghi đầu ra vào luồng, nếu newlineNone thì mọi ký tự '\n' được ghi sẽ được dịch sang dấu phân tách dòng mặc định của hệ thống, os.linesep. Nếu newline'' hoặc '\n' thì không có quá trình dịch thuật nào diễn ra. Nếu newline là bất kỳ giá trị pháp lý nào khác thì mọi ký tự '\n' được viết sẽ được dịch sang chuỗi đã cho.

Nếu line_bufferingTrue, thì flush() được ngụ ý khi lệnh gọi viết chứa ký tự dòng mới hoặc dấu xuống dòng.

Nếu write_throughTrue, các lệnh gọi đến write() được đảm bảo không bị lưu vào bộ đệm: mọi dữ liệu được ghi trên đối tượng TextIOWrapper sẽ được xử lý ngay lập tức tới buffer nhị phân cơ bản của nó.

Thay đổi trong phiên bản 3.3: Đối số write_through đã được thêm vào.

Thay đổi trong phiên bản 3.3: Zz003zz mặc định bây giờ là locale.getpreferredencoding(False) thay vì locale.getpreferredencoding(). Không thay đổi tạm thời mã hóa ngôn ngữ bằng locale.setlocale(), hãy sử dụng mã hóa ngôn ngữ hiện tại thay vì mã hóa ưa thích của người dùng.

Thay đổi trong phiên bản 3.10: Đối số encoding hiện hỗ trợ tên mã hóa giả "locale".

Ghi chú

Khi luồng thô cơ bản không bị chặn, BlockingIOError có thể được tăng lên nếu thao tác đọc không thể hoàn thành ngay lập tức.

TextIOWrapper cung cấp các thuộc tính và phương thức dữ liệu này ngoài các thuộc tính và phương thức dữ liệu từ TextIOBaseIOBase:

line_buffering

Liệu tính năng đệm dòng có được bật hay không.

write_through

Việc ghi có được chuyển ngay vào bộ đệm nhị phân cơ bản hay không.

Added in version 3.7.

reconfigure(*, encoding=None, errors=None, newline=None, line_buffering=None, write_through=None)

Định cấu hình lại luồng văn bản này bằng cách sử dụng cài đặt mới cho encoding, errors, newline, line_bufferingwrite_through.

Các tham số không được chỉ định sẽ giữ nguyên cài đặt hiện tại, ngoại trừ errors='strict' được sử dụng khi encoding được chỉ định nhưng errors không được chỉ định.

Không thể thay đổi mã hóa hoặc dòng mới nếu một số dữ liệu đã được đọc từ luồng. Mặt khác, có thể thay đổi mã hóa sau khi ghi.

Phương pháp này thực hiện xóa luồng ngầm trước khi thiết lập các tham số mới.

Added in version 3.7.

Thay đổi trong phiên bản 3.11: Phương pháp này hỗ trợ tùy chọn encoding="locale".

seek(cookie, whence=os.SEEK_SET, /)

Đặt vị trí luồng. Trả lại vị trí luồng mới dưới dạng int.

Bốn thao tác được hỗ trợ, được đưa ra bởi các kết hợp đối số sau:

  • seek(0, SEEK_SET): Tua lại về đầu luồng.

  • seek(cookie, SEEK_SET): Khôi phục vị trí trước đó; cookie must be một số được trả về bởi tell().

  • seek(0, SEEK_END): Tua nhanh đến cuối luồng.

  • seek(0, SEEK_CUR): Giữ nguyên vị trí luồng hiện tại.

Bất kỳ kết hợp đối số nào khác đều không hợp lệ và có thể đưa ra ngoại lệ.

tell()

Trả về vị trí luồng dưới dạng số mờ. Giá trị trả về của tell() có thể được cung cấp làm đầu vào cho seek() để khôi phục vị trí luồng trước đó.

class io.StringIO(initial_value='', newline='\n')

Luồng văn bản sử dụng bộ đệm văn bản trong bộ nhớ. Nó kế thừa từ TextIOBase.

Bộ đệm văn bản bị loại bỏ khi phương thức close() được gọi.

Giá trị ban đầu của bộ đệm có thể được đặt bằng cách cung cấp initial_value. Nếu dịch dòng mới được bật, dòng mới sẽ được mã hóa như thể bởi write(). Luồng được định vị ở đầu bộ đệm mô phỏng việc mở một tệp hiện có ở chế độ w+, giúp nó sẵn sàng ghi ngay từ đầu hoặc ghi đè lên giá trị ban đầu. Để mô phỏng việc mở tệp ở chế độ a+ sẵn sàng để thêm vào, hãy sử dụng f.seek(0, io.SEEK_END) để định vị lại luồng ở cuối bộ đệm.

Đối số newline hoạt động giống như đối số TextIOWrapper, ngoại trừ việc khi ghi đầu ra vào luồng, nếu newlineNone thì dòng mới được viết là \n trên tất cả các nền tảng.

StringIO cung cấp phương thức này ngoài các phương thức từ TextIOBaseIOBase:

getvalue()

Trả về str chứa toàn bộ nội dung của bộ đệm. Các dòng mới được giải mã như thể bằng read(), mặc dù vị trí luồng không thay đổi.

Ví dụ sử dụng:

nhập khẩu io

đầu ra = io.StringIO()
out.write('Dòng đầu tiên.\n')
print('Dòng thứ hai.', file=output)

nội dung tập tin # Retrieve -- đây sẽ là
# 'Dòng đầu tiên.\nDòng thứ hai.\n'
nội dung = đầu ra.getvalue()

đối tượng # Close và loại bỏ bộ nhớ đệm --
# .getvalue() bây giờ sẽ đưa ra một ngoại lệ.
đầu ra.close()
class io.IncrementalNewlineDecoder

Một codec trợ giúp giải mã dòng mới cho chế độ universal newlines. Nó kế thừa từ codecs.IncrementalDecoder.

Gõ tĩnh

Các giao thức sau đây có thể được sử dụng để chú thích các đối số hàm và phương thức cho các hoạt động đọc hoặc ghi luồng đơn giản. Chúng được trang trí bằng @typing.runtime_checkable.

class io.Reader[T]

Giao thức chung để đọc từ một tệp hoặc luồng đầu vào khác. T thường sẽ là str hoặc bytes, nhưng có thể là bất kỳ loại nào được đọc từ luồng.

Added in version 3.14.

read()
read(size, /)

Đọc dữ liệu từ luồng đầu vào và trả về. Nếu size được chỉ định thì nó phải là số nguyên và tối đa các mục size (byte/ký tự) sẽ được đọc.

Ví dụ:

def read_it(reader: Reader[str]):
    dữ liệu = reader.read(11)
    khẳng định isinstance(data, str)
class io.Writer[T]

Giao thức chung để ghi vào một tập tin hoặc luồng đầu ra khác. T thường sẽ là str hoặc bytes, nhưng có thể là bất kỳ loại nào có thể được ghi vào luồng.

Added in version 3.14.

write(data, /)

Ghi data vào luồng đầu ra và trả về số mục (byte/ký tự) đã ghi.

Ví dụ:

def write_binary(writer: Writer[byte]):
    writer.write(b"Xin chào thế giới!\n")

Xem ABC và các giao thức để làm việc với I/O để biết các lớp và giao thức liên quan đến I/O khác có thể được sử dụng để kiểm tra kiểu tĩnh.

Hiệu suất

Phần này thảo luận về hiệu suất của các triển khai I/O cụ thể được cung cấp.

I/O nhị phân

Bằng cách chỉ đọc và ghi những khối dữ liệu lớn ngay cả khi người dùng yêu cầu một byte đơn, I/O có đệm sẽ che giấu mọi sự kém hiệu quả trong việc gọi và thực thi các quy trình I/O không có bộ đệm của hệ điều hành. Mức tăng phụ thuộc vào hệ điều hành và loại I/O được thực hiện. Ví dụ: trên một số hệ điều hành hiện đại như Linux, I/O đĩa không có bộ đệm có thể nhanh như I/O có bộ đệm. Tuy nhiên, điểm mấu chốt là I/O được đệm mang lại hiệu suất có thể dự đoán được bất kể nền tảng và thiết bị hỗ trợ. Do đó, hầu như luôn luôn ưu tiên sử dụng I/O có bộ đệm hơn là I/O không có bộ đệm cho dữ liệu nhị phân.

Vào/ra văn bản

I/O văn bản qua bộ lưu trữ nhị phân (chẳng hạn như tệp) chậm hơn đáng kể so với I/O nhị phân trên cùng một bộ lưu trữ, vì nó yêu cầu chuyển đổi giữa dữ liệu unicode và nhị phân bằng cách sử dụng codec ký tự. Điều này có thể trở nên đáng chú ý khi xử lý lượng lớn dữ liệu văn bản như các tệp nhật ký lớn. Ngoài ra, tell()seek() đều khá chậm do sử dụng thuật toán tái tạo.

Tuy nhiên, StringIO là vùng chứa unicode trong bộ nhớ gốc và sẽ có tốc độ tương tự như BytesIO.

Đa luồng

Các đối tượng FileIO an toàn theo luồng trong phạm vi hệ điều hành gọi (chẳng hạn như read(2) trong Unix) mà chúng bao bọc cũng an toàn theo luồng.

Các đối tượng được đệm nhị phân (các phiên bản của BufferedReader, BufferedWriter, BufferedRandomBufferedRWPair) bảo vệ cấu trúc bên trong của chúng bằng cách sử dụng khóa; do đó việc gọi chúng từ nhiều luồng cùng một lúc là an toàn.

Các đối tượng TextIOWrapper không an toàn cho luồng.

Tái nhập

Các đối tượng được đệm nhị phân (các phiên bản của BufferedReader, BufferedWriter, BufferedRandomBufferedRWPair) không được cấp lại. Mặc dù các lệnh gọi lại sẽ không xảy ra trong các tình huống thông thường nhưng chúng có thể phát sinh từ việc thực hiện I/O trong trình xử lý signal. Nếu một luồng cố gắng nhập lại một đối tượng được lưu vào bộ đệm mà nó đang truy cập, thì RuntimeError sẽ xuất hiện. Lưu ý rằng điều này không cấm một luồng khác xâm nhập vào đối tượng được đệm.

Phần trên ngầm mở rộng sang các tệp văn bản, vì hàm open() sẽ bọc một đối tượng được lưu vào bộ đệm bên trong TextIOWrapper. Điều này bao gồm các luồng tiêu chuẩn và do đó cũng ảnh hưởng đến chức năng print() tích hợp.