How do I sort out (distinguish) an error derived from a "disk full condition" from "trying to write to a read-only file system"? I don't want to fill my HD to find out :) What I want is to know who to catch each exception, so my code can say something to the user when he is trying to write to a ReadOnly FS and another message if the user is trying to write a file in a disk that is full.
On a read-only filesystem, the files themselves will be marked as read-only. Any attempt to open
a read-only file for writing (O_WRONLY
or O_RDWR
) will fail. On UNIX-like systems, the errno EACCES
will be set.
>>> file('/etc/resolv.conf', 'a') Traceback (most recent call last): File "", line 1, in IOError: [Errno 13] Permission denied: '/etc/resolv.conf'
In contrast, attempts to write
to a full file may result in ENOSPC
. May is critical; the error may be delayed until fsync
or close
.
>>> file(/dev/full, 'a').write('\n') close failed in file object destructor: IOError: [Errno 28] No space left on device
Once you catch IOError
, e.g. with an except IOError, e:
clause in Python 2.*, you can examine e.errno
to find out exactly what kind of I/O error it was (unfortunately in a way that's not necessarily fully portable among different operating systems).
See the errno module in Python standard library; opening a file for writing on a R/O filesystem (on a sensible OS) should produce errno.EPERM
, errno.EACCES
or better yet errno.EROFS
("read-only filesystem"); if the filesystem is R/W but there's no space left you should get errno.ENOSPC
("no space left on device"). But you will need to experiment on the OSes you care about (with a small USB key filling it up should be easy;-).
There's no way to use different except
clauses depending on errno -- such clauses must be distinguished by the class of exceptions they catch, not by attributes of the exception instance -- so you'll need an if/else or other kind of dispatching within a single except IOError, e:
clause.