Python file.writable(): Check Stream Write Capability

The file.writable() method returns True if the underlying file stream supports write operations, and False otherwise. It provides a defensive mechanism to verify stream capabilities before attempting to write data.

Companion Methods: To inspect reading and random-access capabilities of streams, use file.readable() and file.seekable().

Syntax & Parameters 🔝

The writable() method takes no arguments and is called directly on an open file object:

is_writable = file_object.writable()
Parameter Type Required? Description
(None) — No The method accepts no parameters. Passing any arguments raises a TypeError.

Return Value: Returns a boolean (bool):

  • True — if the file stream was opened in a mode that permits writing (such as 'w', 'a', 'x', 'r+', 'w+', 'a+').
  • False — if the file stream is read-only (such as 'r' or 'rb').

Basic Examples: Read vs. Write vs. Append 🔝

Let's open files in different access modes to observe the boolean output of writable():

# 1. Read-only mode ('r')
with open("data.txt", "w") as f_setup:
    f_setup.write("Sample data\n")

with open("data.txt", "r") as f_read:
    print("Read mode ('r'):    ", f_read.writable())  # False

# 2. Write mode ('w')
with open("data.txt", "w") as f_write:
    print("Write mode ('w'):   ", f_write.writable())  # True

# 3. Append mode ('a')
with open("data.txt", "a") as f_append:
    print("Append mode ('a'):  ", f_append.writable())  # True

# 4. Read + Write mode ('r+')
with open("data.txt", "r+") as f_plus:
    print("Read+Write ('r+'):  ", f_plus.writable())    # True
Expected Output
Read mode ('r'):     False
Write mode ('w'):    True
Append mode ('a'):   True
Read+Write ('r+'):   True

Complete File Modes Matrix 🔝

Python's built-in open() function supports numerous mode combinations. Here is how each mode responds to writable() and readable():

Mode Operation Description readable() writable() Initial Pointer Position
'r' / 'rb' Read only (default) True False Beginning of file (0)
'w' / 'wb' Truncate & write only False True Beginning of file (0)
'a' / 'ab' Append only False True End of file (EOF)
'x' / 'xb' Exclusive creation & write False True Beginning of file (0)
'r+' / 'r+b' Read and write (no truncation) True True Beginning of file (0)
'w+' / 'w+b' Truncate, read, and write True True Beginning of file (0)
'a+' / 'a+b' Read and append True True End of file (EOF)

Preventing io.UnsupportedOperation: not writable 🔝

If your code calls write() on a stream that was opened in read-only mode, Python raises io.UnsupportedOperation: not writable (which is a subclass of OSError and ValueError):

import io

with open("data.txt", "r") as f:
    try:
        f.write("New Content")
    except io.UnsupportedOperation as err:
        print("Write failed:", err)
Expected Output
Write failed: not writable

Defensive Programming Pattern: Checking f.writable() before writing allows modular functions to fail early or fall back gracefully rather than crashing in the middle of processing:

def safe_append_log(stream, message):
    if not stream.writable():
        print("Warning: Stream is not writable. Log omitted.")
        return False
    stream.write(f"[LOG] {message}\n")
    return True

Closed File Behavior & ValueError 🔝

Calling writable() on a file that has already been closed raises a ValueError:

f = open("data.txt", "w")
f.close()

try:
    f.writable()
except ValueError as err:
    print("Error caught:", err)
# Output: Error caught: I/O operation on closed file.

To safely inspect an uncertain file handle, check not f.closed and f.writable().

In-Memory Streams: io.StringIO and io.BytesIO 🔝

Python's io.StringIO and io.BytesIO memory streams implement the same file interface as disk files, and their writable() method returns True by default:

import io

mem_stream = io.StringIO("Initial text in memory")

print("Memory stream writable:", mem_stream.writable())  # True
print("Memory stream readable:", mem_stream.readable())  # True

The Stream Capability Trio: readable(), writable(), seekable() 🔝

Python standard library streams adhere to three core capability queries:

  • f.readable() — Determines if the stream supports read() and readline().
  • f.writable() — Determines if the stream supports write() and writelines().
  • f.seekable() — Determines if the stream supports random cursor jumps via seek() and position queries via tell(). (For instance, network sockets, named pipes, and standard input streams return False for seekable()).

Hands-on Exercise: Defensive Logger with Assertions 🔝

Let's build a robust stream dispatcher that inspects incoming file handles, writes audit events when permitted, and returns structured validation status, verified with unit assertions:

Python Exercise: Stream Capability Auditor
import io
import tempfile

def audit_and_write(stream, event_message):
    # Defensive capability audit
    if stream.closed:
        return {"status": "ERROR", "reason": "CLOSED"}
    
    if not stream.writable():
        return {"status": "REJECTED", "reason": "NOT_WRITABLE"}
        
    stream.write(f"AUDIT: {event_message}\n")
    return {"status": "SUCCESS", "reason": None}

# Test Case 1: Writable in-memory stream
mem = io.StringIO()
res1 = audit_and_write(mem, "User login from IP 192.168.1.1")
assert res1["status"] == "SUCCESS"
assert mem.getvalue() == "AUDIT: User login from IP 192.168.1.1\n"

# Test Case 2: Read-only temporary file
with tempfile.NamedTemporaryFile(mode="w+") as temp:
    temp.write("Existing data\n")
    temp.flush()
    
    with open(temp.name, "r") as read_only_f:
        res2 = audit_and_write(read_only_f, "Should not be written")
        assert res2["status"] == "REJECTED"
        assert res2["reason"] == "NOT_WRITABLE"

# Test Case 3: Closed stream
closed_stream = io.StringIO()
closed_stream.close()
res3 = audit_and_write(closed_stream, "Attempt on closed")
assert res3["status"] == "ERROR"
assert res3["reason"] == "CLOSED"

print("All stream capability audit assertions passed successfully!")



Subscribe to our YouTube Channel here



plus2net.com







Python Video Tutorials
Python SQLite Video Tutorials
Python MySQL Video Tutorials
Python Tkinter Video Tutorials
✖
We use cookies to improve your browsing experience. . Learn more
HTML MySQL PHP JavaScript ASP Photoshop Articles Contact us
© 2000-2026 plus2net.com All rights reserved worldwide Privacy Policy Disclaimer