# io.Buffered{Random, Reader, Writer, RWPair} buffer\_size cannot be None

**URL:** <https://discuss.python.org/t/io-buffered-random-reader-writer-rwpair-buffer-size-cannot-be-none/104783>\
**Category:** Ideas\
**Created:** [November 8, 2025, 8:32pm UTC](https://discuss.python.org/t/io-buffered-random-reader-writer-rwpair-buffer-size-cannot-be-none/104783 "2025-11-08T20:32:48Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![tcyrus](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/tcyrus/32/32339_2.png) [@tcyrus](https://discuss.python.org/u/tcyrus)\
**Post date:** [November 8, 2025, 8:32pm UTC](https://discuss.python.org/t/io-buffered-random-reader-writer-rwpair-buffer-size-cannot-be-none/104783/1 "2025-11-08T20:32:48Z")

</div>

The `io.Buffered{Random, Reader, Writer, RWPair}` constructor(s) currently throw a `ValueError` if `buffer_size` is `None`

The docs say:

> If _buffer\_size_ is omitted, `DEFAULT_BUFFER_SIZE` is used.

I believe that the ommited argument behavior should be extended to cover `None` inputs

---

<div class="post-metadata">

**Author:** ![cmaloney](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/cmaloney/32/15851_2.png) [@cmaloney](https://discuss.python.org/u/cmaloney)\
**Post date:** [November 8, 2025, 8:55pm UTC](https://discuss.python.org/t/io-buffered-random-reader-writer-rwpair-buffer-size-cannot-be-none/104783/2 "2025-11-08T20:55:38Z")

</div>

What is the behavior of `.peek()` with `buffer_size=None`?

I have been trying to implement this as well as evolve Buffed I/O in general a bit (see: [Reworking "Buffered I/O" in CPython](http://discuss.python.org/t/reworking-buffered-i-o-in-cpython/90019), I refer to this as `buffer_size=0` / `buffering=0`). The code internally is structured to require a buffer at the moment but that is definitely changeable.

---

<div class="post-metadata">

**Author:** ![gcewing](https://avatars.discourse-cdn.com/v4/letter/g/3d9bf3/32.png) [@gcewing](https://discuss.python.org/u/gcewing)\
**Post date:** [November 9, 2025, 2:16am UTC](https://discuss.python.org/t/io-buffered-random-reader-writer-rwpair-buffer-size-cannot-be-none/104783/3 "2025-11-09T02:16:09Z")

</div>

Seems to me you need a minimum buffer size of 1 for peek() to work, at least until the peeked character is read. You could temporarily change the buffer size behind the scenes, but that could break code that has requested no buffering for a reason. I’d vote for simply disallowing peek() if buffer\_size = 0.

---

<div class="post-metadata">

**Author:** ![MegaIng](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/megaing/32/16162_2.png) [@MegaIng](https://discuss.python.org/u/MegaIng)\
**Post date:** [November 9, 2025, 3:16am UTC](https://discuss.python.org/t/io-buffered-random-reader-writer-rwpair-buffer-size-cannot-be-none/104783/4 "2025-11-09T03:16:49Z")

</div>

> [@cmaloney](#):
>
> I have been trying to implement this as well as evolve Buffed I/O in general a bit (see: [Reworking “Buffered I/O” in CPython](http://discuss.python.org/t/reworking-buffered-i-o-in-cpython/90019), I refer to this as `buffer_size=0` / `buffering=0`).

Note that what OP asked for is _not_ for `buffer_size=None` to be the same as `buffer_size=0`. They ask for it to be equivalent to not providing `buffer_size` at all. This is ~always a good idea to simplify the process of creating wrappers, but the fact that `buffer_size=0` has a different meaning makes it IMO not an obvious choice.

---

<div class="post-metadata">

**Author:** ![cmaloney](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/cmaloney/32/15851_2.png) [@cmaloney](https://discuss.python.org/u/cmaloney)\
**Post date:** [November 9, 2025, 3:49am UTC](https://discuss.python.org/t/io-buffered-random-reader-writer-rwpair-buffer-size-cannot-be-none/104783/5 "2025-11-09T03:49:03Z")

</div>

> [@MegaIng](#):
>
> They ask for it to be equivalent to not providing `buffer_size` at all

Re-reading I agree that seems to be the initial ask. Making `buffer_size=None` mean “use the default” I can see but to me that reads ambiguously with “None means no buffer”
