Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

"file" does not work with the "with" statement!

0 views
Skip to first unread message

Michele Simionato

unread,
Dec 10, 2009, 4:13:47 AM12/10/09
to
I have just discovered that the syntax

with file(name, 'w') as f:
do_something(f)

does not close the file at the end of the with statement! On the
contrary

with open(name, 'w') as f:
do_something(f)

works fine. The docs say "When opening a file, it’s preferable to use
open() instead of invoking this constructor directly." but perhaps
they should mention why :(

Peter Otten

unread,
Dec 10, 2009, 4:59:03 AM12/10/09
to
Michele Simionato wrote:

Are you sure?

Python 2.6.4 (r264:75706, Nov 2 2009, 14:44:17)
[GCC 4.4.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> with file("tmp.txt", "w") as f:
... print >> f, "whatever"
...
>>> f.write("something")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: I/O operation on closed file

Peter

Diez B. Roggisch

unread,
Dec 10, 2009, 5:04:40 AM12/10/09
to
Michele Simionato wrote:

Are you sure? For me on python2.5, it works as advertised:

from __future__ import with_statement

def test(outf):
with outf:
outf.write("test\n")
try:
outf.write("test\n")
assert False, "Not closed"
except ValueError:
pass

outf = open("/tmp/foo", "w")
test(outf)
outf = file("/tmp/bar", "w")
test(outf)

Which Python do you use?

Diez

Michele Simionato

unread,
Dec 10, 2009, 5:29:20 AM12/10/09
to
On Dec 10, 11:04 am, "Diez B. Roggisch" <de...@nospam.web.de> wrote:
> Are you sure? For me on python2.5, it works as advertised:
>
> from __future__ import with_statement
>
> def test(outf):
>     with outf:
>         outf.write("test\n")
>     try:
>         outf.write("test\n")
>         assert False, "Not closed"
>     except ValueError:
>         pass
>
> outf = open("/tmp/foo", "w")
> test(outf)
> outf = file("/tmp/bar", "w")
> test(outf)
>
> Which Python do you use?
>
> Diez

Python 2.5, but it could be an artifact of the way I am looking if a
file is closed.
I have subclassed the file builtin, added a .close method and it was
not called by the
"with" statement. This during debugging, but now I have found another
reason to explain why I was
running out of file descriptors, (I was opening too many connections
to the db).
It is entirely possible that the problem was not with the "with"
statement.

Diez B. Roggisch

unread,
Dec 10, 2009, 5:35:18 AM12/10/09
to
Michele Simionato wrote:

> On Dec 10, 11:04 am, "Diez B. Roggisch" <de...@nospam.web.de> wrote:
>> Are you sure? For me on python2.5, it works as advertised:
>>
>> from __future__ import with_statement
>>
>> def test(outf):
>> with outf:
>> outf.write("test\n")
>> try:
>> outf.write("test\n")
>> assert False, "Not closed"
>> except ValueError:
>> pass
>>
>> outf = open("/tmp/foo", "w")
>> test(outf)
>> outf = file("/tmp/bar", "w")
>> test(outf)
>>
>> Which Python do you use?
>>
>> Diez
>
> Python 2.5, but it could be an artifact of the way I am looking if a
> file is closed.

The above ran on python2.5 for me, no hitch.

> I have subclassed the file builtin, added a .close method and it was
> not called by the
> "with" statement. This during debugging, but now I have found another
> reason to explain why I was
> running out of file descriptors, (I was opening too many connections
> to the db).
> It is entirely possible that the problem was not with the "with"
> statement.

Probably. Closing a file through with might not involve calling close() - it
might be implemented differently in __exit__.

So overload *that*, too.

Diez

Peter Otten

unread,
Dec 10, 2009, 5:55:53 AM12/10/09
to
Michele Simionato wrote:

Subclassing file doesn't work properly:

http://mail.python.org/pipermail/python-list/2005-April/920562.html

Peter

Christian Heimes

unread,
Dec 10, 2009, 5:59:55 AM12/10/09
to Michele Simionato, pytho...@python.org
Michele Simionato wrote:
> Python 2.5, but it could be an artifact of the way I am looking if a
> file is closed.
> I have subclassed the file builtin, added a .close method and it was
> not called by the
> "with" statement. This during debugging, but now I have found another
> reason to explain why I was
> running out of file descriptors, (I was opening too many connections
> to the db).
> It is entirely possible that the problem was not with the "with"
> statement.

In Python 2.5 you have to implement your own __enter__ and __exit__
methods if you subclass from file. The file.__exit__ function doesn't
call f.close(). The minor inconsistency has been fixed in Python 2.6.


Python 2.5:

static PyObject *
file_exit(PyFileObject *f, PyObject *args)
{
PyObject *ret = file_close(f);
if (!ret)
/* If error occurred, pass through */
return NULL;
Py_DECREF(ret);
/* We cannot return the result of close since a true
* value will be interpreted as "yes, swallow the
* exception if one was raised inside the with block". */
Py_RETURN_NONE;
}

Python 2.6:

static PyObject *
file_exit(PyObject *f, PyObject *args)
{
PyObject *ret = PyObject_CallMethod(f, "close", NULL);
if (!ret)
/* If error occurred, pass through */
return NULL;
Py_DECREF(ret);
/* We cannot return the result of close since a true
* value will be interpreted as "yes, swallow the
* exception if one was raised inside the with block". */
Py_RETURN_NONE;
}

Michele Simionato

unread,
Dec 10, 2009, 6:59:31 AM12/10/09
to
On Dec 10, 11:59 am, Christian Heimes <li...@cheimes.de> wrote:
> In Python 2.5 you have to implement your own __enter__ and __exit__
> methods if you subclass from file. The file.__exit__ function doesn't
> call f.close().

Yes, that was my problem.

0 new messages