-
-
Notifications
You must be signed in to change notification settings - Fork 31.6k
io.FileIO calls flush() after file closed #49950
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
>>> import io
>>> class MyIO(io.FileIO):
... def flush(self):
... print('closed:', self.closed)
...
>>> f = MyIO('test.out', 'wb')
>>> f.close()
closed: True IMHO, calling flush() after the file has already been closed is |
Discussion about this bug is ongoing in python-dev. |
cooperation.diff:
|
Is it really necessary (e.g. to pass the tests)? |
It is necessary to make MI work. With out it the inheritance graph looks io.IOBase _pyio.IOBase If you call MyClass.flush() with this hierarchy then it will propagate There are other ways you could solve this, of course, like getting But it seems like this is the right way to fix this problem anyway - as |
MyMixin doesn't need to inherit from IOBase, since precisely it is a
That's because the reference ABCs are defined in the io module, not in True
>>> issubclass(_pyio.FileIO, io.IOBase)
True
>>> issubclass(io.TextIOWrapper, io.IOBase)
True
>>> issubclass(_pyio.TextIOWrapper, io.IOBase)
True _pyio.IOBase and friends are just concrete implementations of those True
>>> issubclass(_pyio.TextIOBase, io.TextIOBase)
True I know it looks a bit non-intuitive at first, but the point is that the |
Antoine Pitrou wrote:
In my implementation, it does. Otherwise the linearization of the class MyClass -> io.FileIO -> io.IOBase -> MyMixin (-> _pyio.IOBase) But io.IOBase doesn't make super calls so MyMixin method won't be called. I think that this linearization is probably more useful: MyClass -> io.FileIO -> MyMixin -> IOBase And you get that when io.FileIO and MyMixin share the same IOBase as a I don't mind changing io.IOBase to make super calls in ._close() and [snipped]
I'm not trying to change the ABC unification at all - and if I did then Cheers, |
But why not simply: MyClass -> MyMixin -> io.FileIO -> IOBase ?
I understand, but that's at the price of an otherwise useless |
Antoine Pitrou wrote:
No, doing this is trivial. But shouldn't it be up to the implementor of
Maybe I misunderstand the purpose of _pyio. The Python 3.1 says that its I, for example, want to add a sync() method to FileIO that will call Cheers, |
Is there a concrete use case, though? By the way, what if _pyio.FileIO inherited from io.FileIO instead of |
Antoine Pitrou wrote:
I don't have a good one in mind - though
I don't think that would work - but reasoning about MRO hurts my brain ;-) You'd have to declare the class like this: class FileIO(io.FileIO, IOBase):
pass to get the io.File methods to resolve first. But that means that the Cheers, |
Oops, I didn't finish my thought:
I don't have a good one in mind - though writing the unit test |
The original snippet works the same on 3.2.0. Was their any conclusion as to whether or not a change should be made? |
There is complete implementation of FileIO in pure Python in bpo-21859. It is free from this bug. >>> import _pyio as io
>>> class MyIO(io.FileIO):
... def flush(self):
... print('closed:', self.closed)
...
>>> f = MyIO('test.out', 'wb')
>>> f.close()
closed: False |
Yet one related bug is that flush() isn't called at all if the file was opened with closefd=False. >>> import io, os
>>> class MyIO(io.FileIO):
... def flush(self):
... print('closed:', self.closed)
...
>>> fd = os.open('test.out', os.O_WRONLY|os.O_CREAT)
>>> f = MyIO(fd, 'wb', closefd=False)
>>> f.close() The proposed simple patch fixes both bugs. |
Ping. |
Added comments as Antoine suggested. |
And here is a patch for 2.7. |
For the record, the python-dev thread referenced in the original post is <https://mail.python.org/pipermail/python-dev/2009-April/088212.html\>. The obvious fix to me is to have FileIO.close() call IOBase.close() to invoke the flush() before continuing with its own closing. This is what Serhiy’s patches appear to do, so I agree with them in general. I do wonder what the point of duplicating test code in test_io and test_fileio is. The only difference seems to be calling open() versus calling FileIO() directly. Wouldn’t it be better to merge the code together, or maybe just assert open() returns a FileIO instance? |
Agree, the test in test_fileio is redundant. |
New changeset 7052206ad381 by Serhiy Storchaka in branch '2.7': New changeset 36f5c36b7704 by Serhiy Storchaka in branch '3.4': New changeset e1f08f5b6b62 by Serhiy Storchaka in branch 'default': |
New changeset bf52f69d6948 by Serhiy Storchaka in branch '2.7': New changeset 00bde0743690 by Serhiy Storchaka in branch '3.4': New changeset a8df1ca60452 by Serhiy Storchaka in branch 'default': |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: