Skip to content

Commit 3e94e40

Browse files
nightcitybladeclaude
andcommitted
Document wrap_file behavior regarding close, GC, and concurrent access
Clarify in the wrap_file docstring that closing the async wrapper closes the underlying file, that GC does not auto-close, and that the original sync file should not be used concurrently. Closes #3379 Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
1 parent 3dd35d7 commit 3e94e40

1 file changed

Lines changed: 13 additions & 0 deletions

File tree

src/trio/_file_io.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,19 @@ def wrap_file(file: FileT) -> AsyncIOWrapper[FileT]:
493493
Returns:
494494
An :term:`asynchronous file object` that wraps ``file``
495495
496+
The returned wrapper object shares the underlying file with the original
497+
``file`` object; it does not copy it. Closing the wrapper (via
498+
:meth:`~trio.abc.AsyncResource.aclose` or ``async with``) will close the
499+
underlying file. However, if the wrapper is garbage collected without
500+
being explicitly closed, the underlying file is *not* closed
501+
automatically — you should always close it explicitly.
502+
503+
The original synchronous file object should not be used directly while
504+
the wrapper exists, as the wrapper may call file methods in a worker
505+
thread, and concurrent access from multiple threads is not safe for most
506+
file objects. If you need synchronous access, use the
507+
:attr:`~AsyncIOWrapper.wrapped` attribute.
508+
496509
Example::
497510
498511
async_file = trio.wrap_file(StringIO('asdf'))

0 commit comments

Comments
 (0)