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
File mode wb+ appears as rb+ #69528
Comments
There is at least one mode in which a file can be opened that cannot be represented in its mode attribute: wb+. This mode instead appears as 'rb+' in the mode attribute: Python 3.5.0 (default, Oct 3 2015, 10:40:38)
[GCC 4.2.1 Compatible FreeBSD Clang 3.4.1 (tags/RELEASE_34/dot1-final 208032)] on freebsd10
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> if os.path.exists('some_file'): os.unlink('some_file')
...
>>> with open('some_file', 'r+b') as f: print(f.mode)
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: 'some_file'
>>> with open('some_file', 'w+b') as f: print(f.mode)
...
rb+
>>> with open('some_file', 'r+b') as f: print(f.mode)
rb+ This means code that interacts with file objects cannot trust the mode of binary files. For example, you can't use tempfile.TemporaryFile (the mode argument of which defaults to 'wb+') and GzipFile: >>> import gzip
>>> from tempfile import TemporaryFile
>>> with TemporaryFile() as f:
... gzip.GzipFile(fileobj=f).write(b'test')
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "/usr/local/lib/python3.5/gzip.py", line 249, in write
raise OSError(errno.EBADF, "write() on read-only GzipFile object")
OSError: [Errno 9] write() on read-only GzipFile object This occurs because without a mode argument passed to its initializer, GzipFile checks that the fp object's mode starts with 'w', 'a', or 'x'. For the sake of completeness/searchability: w+ and r+ are different modes, so rb+ and wb+ must be different modes. Per https://docs.python.org/3/library/functions.html#open : """ I haven't been able to test this on Windows, but I expect precisely the same behavior given my understanding of the relevant source. _io_FileIO___init___impl in _io/fileio.c does the right thing and includes O_CREAT and O_TRUNC in the open(2) flags upon seeing 'w' in the mode: https://hg.python.org/cpython/file/3.5/Modules/_io/fileio.c#l324 this ensures correct interaction with the file system. But it also sets self->readable and self->writable upon seeing '+' in the mode: https://hg.python.org/cpython/file/3.5/Modules/_io/fileio.c#l341 The open flags are not retained. Consequently, when the mode attribute is accessed and the get_mode calls the mode_string function, the instance has insufficient information to differentiate between 'rb+' and 'wb+': https://hg.python.org/cpython/file/3.5/Modules/_io/fileio.c#l1043 If the FileIO instance did retain the 'flags' variable that's declared and set in its initializer, then mode_string could use it to determine the difference between wb+ and rb+. I would be happy to write a patch for this. |
I think Mark is right. Since wb+ and rb+ have different behaviours they But this behaviour treating wb+ and rb+ as the same is well tested and |
Python's test suite may test the current behavior but that does not lessen I gave an example of apparently correct code that fails (that was actually Another way to think about the problem is accuracy of intent. The mode On Sat, Oct 10, 2015 at 1:27 AM, Xiang Zhang <report@bugs.python.org> wrote:
|
I make a patch which now identifies the difference between wb+ and rb+, |
I think this is not intended behavior. Tests just test that the current behavior is not changed accidentally. If I'm right, the patch LGTM. But since third-party code can depend on this behavior, I would fix it only in 3.6. Tests were added in bpo-4362 and Barry asked the same question about "w+" (msg76134). Barry, Benjamin, what are you think about this now? |
Reproduced on 3.11. |
I think this is a problem in gzip. It has only READ and WRITE modes, and it ignores the '+'. |
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: