io --- luồng đầu vào/đầu ra¶
Mô-đun này chứa các loại đối tượng stream (dạng tệp) bổ sung và các hàm tiện ích. Nó cung cấp hàm dựng sẵn open() cùng với các bộ đệm văn bản và nhị phân trong bộ nhớ (StringIO, BytesIO) triển khai giao diện luồng chuẩn read/write/seek.
Phân cấp khái niệm¶
Sự khác biệt với CPython
Phân cấp khái niệm của các lớp cơ sở luồng được đơn giản hóa trong MicroPython, như mô tả trong phần này.
Các lớp cơ sở luồng (trừu tượng), đóng vai trò nền tảng cho hành vi của tất cả các lớp cụ thể, tuân theo một số lưỡng phân (phân loại theo cặp) trong CPython. Trong MicroPython, chúng được đơn giản hóa và làm ẩn đi phần nào để đạt hiệu quả cao hơn và tiết kiệm tài nguyên.
Một lưỡng phân quan trọng trong CPython là luồng không có bộ đệm so với có bộ đệm. Trong MicroPython, hiện tại tất cả các luồng đều không có bộ đệm. Điều này là vì tất cả các hệ điều hành hiện đại, và thậm chí nhiều RTOS và trình điều khiển hệ thống tệp đã thực hiện bộ đệm ở phía của chúng. Thêm một lớp bộ đệm nữa sẽ phản tác dụng (một vấn đề được gọi là "bufferbloat") và tốn bộ nhớ quý giá. Lưu ý rằng vẫn có những trường hợp bộ đệm có thể hữu ích, vì vậy chúng tôi có thể giới thiệu hỗ trợ bộ đệm tùy chọn vào thời điểm sau.
Nhưng trong CPython, một lưỡng phân quan trọng khác gắn liền với "tính có bộ đệm" - đó là liệu một luồng có thể gây ra thao tác đọc/ghi ngắn hay không. Đọc ngắn là khi người dùng yêu cầu ví dụ 10 byte từ một luồng, nhưng nhận được ít hơn, tương tự đối với ghi. Trong CPython, các luồng không có bộ đệm tự động dễ bị thao tác ngắn, trong khi có bộ đệm thì được đảm bảo không có. Không có thao tác đọc/ghi ngắn là đặc điểm quan trọng, vì nó cho phép phát triển các chương trình ngắn gọn và hiệu quả hơn - điều rất đáng mong muốn cho MicroPython. Vì vậy, mặc dù MicroPython không hỗ trợ luồng có bộ đệm, nhưng nó vẫn cung cấp các luồng không có thao tác ngắn. Liệu có thao tác ngắn hay không phụ thuộc vào nhu cầu của từng lớp cụ thể, nhưng các nhà phát triển được khuyến khích mạnh mẽ ưu tiên hành vi không có thao tác ngắn vì những lý do nêu trên. Ví dụ, các socket MicroPython được đảm bảo tránh thao tác đọc/ghi ngắn. Thực tế, tại thời điểm này, không có ví dụ nào về lớp luồng có thao tác ngắn trong nhân, và lớp như vậy sẽ dành riêng cho phần cứng cụ thể.
Hành vi không có thao tác ngắn trở nên phức tạp trong trường hợp luồng không chặn, với chặn so với không chặn là một lưỡng phân CPython khác, được hỗ trợ đầy đủ bởi MicroPython. Luồng không chặn không bao giờ chờ dữ liệu đến hoặc được ghi - chúng đọc/ghi những gì có thể, hoặc báo hiệu thiếu dữ liệu (hoặc khả năng ghi dữ liệu). Rõ ràng, điều này mâu thuẫn với chính sách "không có thao tác ngắn", và thực sự, trường hợp luồng không chặn có bộ đệm (và do đó không có thao tác ngắn) rất phức tạp trong CPython - ở một số chỗ, sự kết hợp đó bị cấm, ở một số chỗ nó không được xác định hoặc chưa được ghi lại, ở một số trường hợp nó đưa ra ngoại lệ dài dòng. Vấn đề đơn giản hơn nhiều trong MicroPython: luồng không chặn quan trọng cho các hoạt động bất đồng bộ hiệu quả, vì vậy thuộc tính này được ưu tiên hơn "không có thao tác ngắn". Vì vậy, trong khi các luồng chặn sẽ tránh đọc/ghi ngắn bất cứ khi nào có thể (trường hợp duy nhất để nhận đọc ngắn là nếu đến cuối tệp, hoặc trong trường hợp lỗi (nhưng lỗi không trả về dữ liệu ngắn mà đưa ra ngoại lệ)), các luồng không chặn có thể tạo ra dữ liệu ngắn để tránh chặn thao tác.
Lưỡng phân cuối cùng là luồng nhị phân so với văn bản. MicroPython dĩ nhiên hỗ trợ những loại này, nhưng trong khi trong CPython các luồng văn bản có bộ đệm một cách nội tại, thì trong MicroPython chúng không như vậy. (Thực vậy, đó là một trong những trường hợp mà chúng tôi có thể giới thiệu hỗ trợ bộ đệm.)
Lưu ý rằng vì hiệu quả, MicroPython không cung cấp các lớp cơ sở trừu tượng tương ứng với phân cấp trên, và không thể triển khai hoặc phân lớp con một lớp luồng bằng Python thuần túy.
Các hàm¶
Các lớp¶
- class io.IOBase¶
Lớp cơ sở cho các đối tượng luồng ("dạng tệp"). Các lớp con cụ thể triển khai các phương thức I/O cấp thấp bên dưới (
readinto,write,ioctl); runtime xây dựng giao thức luồng cấp cao hơn (read,readline,readlines,close, lặp) trên đầu chúng, vì vậy mọi thực thể luồng đều hỗ trợ các phương thức đó ngay cả khi lớp con không định nghĩa chúng.Các phương thức triển khai (ghi đè những phương thức này trong lớp con):
- readinto(buf: bytearray) int | None¶
Đọc các byte vào bộ đệm ghi được buf. Trả về số byte đã đọc,
0ở cuối luồng, hoặcNonenếu không có dữ liệu hiện tại (đối với luồng không chặn).
- write(buf: bytes) int | None¶
Ghi các byte trong buf. Trả về số byte đã ghi, hoặc
Nonenếu việc ghi không thể thực hiện ngay lúc này (đối với luồng không chặn).
- ioctl(request: int, arg: int) int¶
Điều khiển luồng/thiết bị bên dưới. request là một trong các mã yêu cầu
MP_STREAM_*. Trả về giá trị không âm khi thành công, hoặc giá trịerrnoâm khi có lỗi.
Các phương thức giao thức luồng (có sẵn trên mọi thực thể luồng):
- read(size: int = -1)¶
Đọc và trả về tối đa size byte (hoặc ký tự, ở chế độ văn bản). Nếu size bị bỏ qua hoặc âm, đọc cho đến cuối luồng. Trả về
bytescho luồng nhị phân vàstrcho luồng văn bản; kết quả rỗng cho biết cuối luồng.
- readline(size: int = -1)¶
Đọc và trả về một dòng, bao gồm ký tự xuống dòng ở cuối nếu có. Nếu size được cho, tối đa size byte (hoặc ký tự) được đọc. Trả về
bytes/strrỗng ở cuối luồng.
- readlines() list¶
Đọc đến cuối luồng và trả về một
listcác dòng, mỗi dòng kèm ký tự xuống dòng ở cuối.
- close() None¶
Đóng luồng và giải phóng các tài nguyên bên dưới. Các thao tác trên luồng đã đóng sẽ đưa ra
OSError(hoặcValueErrorđối với luồng trong bộ nhớ).
- seek(offset: int, whence: int = 0) int¶
Thay đổi vị trí luồng hiện tại sang offset byte so với whence (
0= bắt đầu luồng,1= vị trí hiện tại,2= cuối luồng). Trả về vị trí tuyệt đối mới. Đưa raOSErrortrên luồng không hỗ trợ tìm kiếm vị trí.
- flush() None¶
Xả bất kỳ bộ đệm ghi nào, đẩy dữ liệu đang chờ vào thiết bị hoặc tệp bên dưới. Không có tác dụng trên các luồng không có bộ đệm.
Lặp trực tiếp trên một luồng sẽ trả về một dòng mỗi lần lặp -- tương đương với việc gọi
readline()trong một vòng lặp cho đến khi trả về ký tự kết thúc luồng dòng rỗng. Một luồng cũng hỗ trợ giao thức quản lý ngữ cảnh, vì vậywith open(...) as f:sẽ tự động đóng luồng.Ghi chú
Mô-đun luồng của MicroPython cũng cung cấp các hàm trợ giúp C có hậu tố "1" là
mp_stream_read1_obj,mp_stream_readinto1_obj, vàmp_stream_write1_objthực hiện một lần gọi I/O bên dưới thay vì lặp cho đến khi yêu cầu được thực hiện đầy đủ. Chúng được sử dụng nội bộ bởi các lớp nhưmachine.UARTđể triển khairead/writecủa riêng chúng -- nhưng không có lớp luồng chuẩn nào liên kết chúng dưới dạng các phương thức Python có thể gọiread1/readinto1/write1.
- class io.StringIO(string: str = '')¶
Đối tượng dạng tệp trong bộ nhớ cho đầu vào/đầu ra ở chế độ văn bản (tương tự như tệp thông thường được mở với bộ sửa đổi "t"). Nội dung ban đầu có thể được chỉ định bằng tham số string (phải là chuỗi thông thường). Các thực thể cũng hỗ trợ giao thức quản lý ngữ cảnh (có thể dùng trong câu lệnh
with).- read(size: int = -1) str¶
Đọc và trả về tối đa size ký tự. Nếu size bị bỏ qua hoặc âm, đọc và trả về tất cả nội dung còn lại.
- readline(size: int = -1) str¶
Đọc và trả về một dòng. Nếu size được cho, tối đa size ký tự được đọc.
- readinto(buf: bytearray) int¶
Đọc vào bộ đệm ghi được đã được cấp phát trước buf và trả về số byte đã đọc.
- seek(offset: int, whence: int = 0) int¶
Thay đổi vị trí luồng sang offset so với whence (
0= bắt đầu,1= hiện tại,2= cuối) và trả về vị trí tuyệt đối mới.
- close() None¶
Đóng luồng và giải phóng bộ đệm bên dưới. Các thao tác tiếp theo trên luồng đã đóng sẽ đưa ra
ValueError.
- class io.StringIO(alloc_size: int)
Tạo một đối tượng
StringIOrỗng được cấp phát trước để chứa tối đa alloc_size byte, vì vậy việc ghi tối đa số byte đó sẽ không cấp phát lại bộ đệm (tránh tình huống hết bộ nhớ hoặc phân mảnh bộ nhớ). Constructor này là phần mở rộng MicroPython, chỉ khuyến nghị cho các trường hợp đặc biệt và thư viện cấp hệ thống, không dành cho ứng dụng người dùng cuối.Sự khác biệt với CPython
Constructor này là phần mở rộng MicroPython.
- read(size: int = -1) str
Đọc và trả về tối đa size ký tự. Nếu size bị bỏ qua hoặc âm, đọc và trả về tất cả nội dung còn lại.
- readinto(buf: bytearray) int
Đọc vào bộ đệm ghi được đã được cấp phát trước buf và trả về số byte đã đọc.
- seek(offset: int, whence: int = 0) int
Thay đổi vị trí luồng sang offset so với whence (
0= bắt đầu,1= hiện tại,2= cuối) và trả về vị trí tuyệt đối mới.
- tell() int
Trả về vị trí luồng hiện tại.
- flush() None
Xả các bộ đệm ghi. Đây là thao tác không có tác dụng đối với luồng trong bộ nhớ.
- close() None
Đóng luồng và giải phóng bộ đệm bên dưới. Các thao tác tiếp theo trên luồng đã đóng sẽ đưa ra
ValueError.
- getvalue() str
Trả về nội dung hiện tại của bộ đệm bên dưới.
- class io.BytesIO(string: bytes = b'')¶
Đối tượng dạng tệp trong bộ nhớ cho đầu vào/đầu ra ở chế độ nhị phân (tương tự như tệp thông thường được mở với bộ sửa đổi "b"). Nội dung ban đầu có thể được chỉ định bằng tham số string (phải là đối tượng bytes). Các thực thể cũng hỗ trợ giao thức quản lý ngữ cảnh (có thể dùng trong câu lệnh
with).- read(size: int = -1) bytes¶
Đọc và trả về tối đa size byte. Nếu size bị bỏ qua hoặc âm, đọc và trả về tất cả nội dung còn lại.
- readline(size: int = -1) bytes¶
Đọc và trả về một dòng. Nếu size được cho, tối đa size byte được đọc.
- readinto(buf: bytearray) int¶
Đọc vào bộ đệm ghi được đã được cấp phát trước buf và trả về số byte đã đọc.
- seek(offset: int, whence: int = 0) int¶
Thay đổi vị trí luồng sang offset so với whence (
0= bắt đầu,1= hiện tại,2= cuối) và trả về vị trí tuyệt đối mới.
- close() None¶
Đóng luồng và giải phóng bộ đệm bên dưới. Các thao tác tiếp theo trên luồng đã đóng sẽ đưa ra
ValueError.
- class io.BytesIO(alloc_size: int)
Tạo một đối tượng
BytesIOrỗng được cấp phát trước để chứa tối đa alloc_size byte, vì vậy việc ghi tối đa số byte đó sẽ không cấp phát lại bộ đệm (tránh tình huống hết bộ nhớ hoặc phân mảnh bộ nhớ). Constructor này là phần mở rộng MicroPython, chỉ khuyến nghị cho các trường hợp đặc biệt và thư viện cấp hệ thống, không dành cho ứng dụng người dùng cuối.Sự khác biệt với CPython
Constructor này là phần mở rộng MicroPython.
- read(size: int = -1) bytes
Đọc và trả về tối đa size byte. Nếu size bị bỏ qua hoặc âm, đọc và trả về tất cả nội dung còn lại.
- readline(size: int = -1) bytes
Đọc và trả về một dòng. Nếu size được cho, tối đa size byte được đọc.
- readinto(buf: bytearray) int
Đọc vào bộ đệm ghi được đã được cấp phát trước buf và trả về số byte đã đọc.
- seek(offset: int, whence: int = 0) int
Thay đổi vị trí luồng sang offset so với whence (
0= bắt đầu,1= hiện tại,2= cuối) và trả về vị trí tuyệt đối mới.
- tell() int
Trả về vị trí luồng hiện tại.
- flush() None
Xả các bộ đệm ghi. Đây là thao tác không có tác dụng đối với luồng trong bộ nhớ.
- close() None
Đóng luồng và giải phóng bộ đệm bên dưới. Các thao tác tiếp theo trên luồng đã đóng sẽ đưa ra
ValueError.
- getvalue() bytes
Trả về nội dung hiện tại của bộ đệm bên dưới.