This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Passing a bool to io.open() should raise a TypeError, not read from stdin
Type: behavior Stage: resolved
Components: Versions: Python 3.6, Python 3.4, Python 3.5, Python 2.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: ned.deily, terminalmage
Priority: normal Keywords:

Created on 2018-02-27 21:25 by terminalmage, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (4)
msg313025 - (view) Author: Erik Johnson (terminalmage) Date: 2018-02-27 21:25
When you open a filehandle using either True or False as the file, the open succeeds.

This has been reproduced using op/io.open on Python 3.6.4, 3.5.2, and 3.4.5, as well as with io.open() on Python 2.7.14.

This can be easily demonstrated in the REPL:

>>> f = open(False)
>>> f.read(10)
Lorem ipsum dolor sit amet
'Lorem ipsu'
>>> f.read(10)
'm dolor si'
>>> f.read(10)
't amet\n'
>>> f.read(10)
''
>>> f.close()
>>>
%


After the first read, I pasted in enough to stdin to exceed 10 bytes, and hit Enter. After the 2nd and third reads I had to hit Ctrl-d to exit back to the REPL. And, as a fun bonus, closing the filehandle quits the REPL.


This doesn't look like intended behavior. It doesn't make logical sense (why not just use sys.stdin if you want to read from stdin?), and isn't documented. This should either raise a TypeError, or the behavior should be documented. From the docs:

file is a path-like object giving the pathname (absolute or relative to the current working directory) of the file to be opened or an integer file descriptor of the file to be wrapped. (If a file descriptor is given, it is closed when the returned I/O object is closed, unless closefd is set to False.)

Moreover, when you pass other values that don't match the above description, a TypeError is raised:

>>> open(123.456)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: integer argument expected, got float
>>> open(None)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: expected str, bytes or os.PathLike object, not NoneType
>>> open(['wtf', 'am', 'i', 'doing???'])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: expected str, bytes or os.PathLike object, not list


So, one of str, bytes, and os.PathLike are expected, right? And yet...


>>> isinstance(True, (str, bytes, os.PathLike))
False
>>> isinstance(False, (str, bytes, os.PathLike))
False


It should also be noted that when using the open() builtin on Python 2 instead of io.open(), you get a more logical result:

>>> open(False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: coercing to Unicode: need string or buffer, bool found
msg313026 - (view) Author: Erik Johnson (terminalmage) Date: 2018-02-27 21:27
Please excuse the typo on the 2nd line of the OP, it should say "open/io.open", not "op/io.open".
msg313028 - (view) Author: Erik Johnson (terminalmage) Date: 2018-02-27 21:34
Also, it's the 3rd and 4th reads that I had to hit ctrl-d to get back to the REPL, as you can see in the example the first two read just fine from that initial block of text I had pasted in.

This is what I get for not properly proofreading before I file an issue.
msg313029 - (view) Author: Ned Deily (ned.deily) * (Python committer) Date: 2018-02-27 22:02
Thanks for your report.  Alas, this is expected behavior.  As documented, the Boolean values False and True behave like the integers 0 and 1; this behavior dates back to the earliest days of Python.  So when you pass False to open, you are passing the integer 0 and file number 0 is sys.stdin.

https://docs.python.org/3/library/stdtypes.html#boolean-values
History
Date User Action Args
2022-04-11 14:58:58adminsetgithub: 77146
2018-02-27 22:02:00ned.deilysetstatus: open -> closed

nosy: + ned.deily
messages: + msg313029

resolution: not a bug
stage: resolved
2018-02-27 21:34:27terminalmagesetmessages: + msg313028
2018-02-27 21:27:01terminalmagesetmessages: + msg313026
2018-02-27 21:25:48terminalmagecreate