Article of interest: Python pros/cons for the enterprise

Jeff Schwab jeff at schwabcenter.com
Sun Feb 24 04:22:31 CET 2008


Matthew Woodcraft wrote:
> Jeff Schwab  <jeff at schwabcenter.com> wrote:
>> Matthew Woodcraft wrote:
>>> Jeff Schwab  <jeff at schwabcenter.com> wrote:
>>>> The most traditional, easiest way to open a file in C++ is to use an 
>>>> fstream object, so the file is guaranteed to be closed when the fstream 
>>>> goes out of scope.
>  
>>> Out of interest, what is the usual way to manage errors that the
>>> operating system reports when it closes the file?
> 
>> By default, the fstream object just sets its "failbit," which you can 
>> check manually by calling my_stream.fail().  If you want anything 
>> particular to take place on failure to close a stream, you either have 
>> to call close manually, or you need a dedicated object whose destructor 
>> will deal with it.
> 
>> Alternatively, you can tell the fstream ahead of time that you want 
>> exceptions thrown if particular actions fail.  There's a convention that 
>> destructors don't ever throw exceptions, though, so it would be unusual 
>> to request an exception when close() fails.
> 
> I see. Then, unless you don't care about data loss passing silently,
> this 'most traditional' way to open a file is unsuitable for files
> opened for writing.

No, why would you think so?  If you want something special to happen 
when the close() fails (as you indeed would if you were writing 
important data), you have to say somehow that you want your special code 
called.  What syntax would you like to see?  Here's what the C++ would 
look like, supposing you have a type LoggingCloser that calls close and 
logs any failure:

     void f(std::string file_name) {
         std::ofstream out(file_name.c_str()); // [1]
         LoggingCloser closer(out);

         // ... your work code here ...
     }

The closer's destructor is guaranteed to be called before the file 
stream's.  That gives it a chance to call close manually, and keeps the 
error-handling code separate from the rest of the program logic. 
Compare the following Python equivalent, assuming we've replaced Logging 
Closer's constructor and destructor with __enter__ and __exit__ definitions:

     def f(file_name):
	with file(file_name, 'w') as out:
             with LoggingCloser(out) as closer:
                 // ... your work code here ...

In this case, the Python with-statement is not too bad, because you only 
have two constructor/destructor pairs.  For each new pair, though, it 
seems like you need an extra level of nesting (and therefore 
indentation).  Of course, it may just be that I don't yet know how to 
use the with-statement effectively.

[1] That c_str() kludge is usually the primary complaint about using 
ofstream.  It has been fixed in the new draft standard, which will 
become official in 2009.



More information about the Python-list mailing list