I typed ʻeval ("1/0") `in interactive Python (CPython) in a directory on a machine.
Python 3.5.3 (default, Jan 19 2017, 14:11:04)
[GCC 6.3.0 20170118] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> eval("1/0")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Should I go to bed soon?
File "<string>", line 1, in <module>
It ’s already the limit, right?
ZeroDivisionError: division by zero
Well, divide by zero and run-time error, which is as expected. But, "Why don't you go to bed soon?" "It's already the limit." What is this?
Python on this machine hasn't been modified, and so does the standard library. No program was written to cause this phenomenon. What could be the cause?
Move away from the machine with strange messages and check the nature of Traceback that is displayed when an error occurs.
First, try running the source file hello.py
, which causes division by zero.
hello.py
print(1/0)
$ python3 hello.py
Traceback (most recent call last):
File "hello.py", line 1, in <module>
print(1/0)
ZeroDivisionError: division by zero
Traceback shows that the error occurred on the line print (1/0)
.
This is the expected behavior.
As shown above, it is convenient to see the source code that caused the error in Traceback, but since Python converts the source code to bytecode and then executes it, it does not hold the source code during execution. must.
What's going on.
In fact, Python re-reads the source code after a run-time error to get the code in question.
To confirm this, I created hello2.py
with a line added on top of hello.py
.
hello2.py
input("Please input> ")
print(1/0)
Waits for input at ʻinputbefore division by zero is done. During this time, I will try to rewrite the source code of
hello2.py` itself with an editor.
First, start execution and wait for input.
$ python3 hello2.py
Please input>
Rewrite the second line with appropriate text.
hello2.py (after rewriting)
input("Please input> ")
Are you sleepy?
Give appropriate input to the process waiting for input and proceed with the process.
$ python3 hello2.py
Please input> 123[Enter]
Traceback (most recent call last):
File "hello2.py", line 2, in <module>
Are you sleepy?
ZeroDivisionError: division by zero
It was a division by zero error that should have occurred with the code print (1/0)
, but Traceback displayed the rewritten text, "Are you sleepy?"
You can see that the source code is loaded after the error occurs.
But what if you get an error in standard input or string execution?
The code is not saved in a file, so there is nothing to read after the error occurs.
Let's give Python the hello.py
as standard input.
$ python3 < hello.py
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
It is shown to be the first line of <stdin>
, but it does not show the code for the actual error.
So what if you give the code as a command line argument?
$ python3 -c 'print(1/0)'
Traceback (most recent call last):
File "<string>", line 1, in <module>
ZeroDivisionError: division by zero
Similarly, it is shown to be the first line of <string>
, but the code for the error is not displayed.
Whether it's <stdin>
or <string>
, it doesn't actually exist, so you can't get the source code.
<stdin>
and <string>
?The Traceback above displayed something like File" <stdin> "
or File" <string> "
. What is this?
In compile function documentation,
filename The argument must give the file from which the code is read; pass a recognizable value unless it is read from the file (
'<string>'
is commonly used. Masu).
There is.
If there is no source file, the character string indicating the origin of the source code is set as the "file name".
If Python encounters an error executing bytecode, it will trust the "filename" specified here to create a Traceback.
Files such as <stdin>
and <string>
do not exist, so in these cases the code indicating the error location cannot be obtained and nothing is displayed there.
But are there absolutely no files like <stdin>
or <string>
?
What if there was?
These files are prepared in a certain directory on a certain machine introduced at the beginning.
$ ls
<stdin> <string>
$ cat '<stdin>'
Should I go to bed soon?
$ cat '<string>'
It ’s already the limit, right?
Since the input to Python's interactive mode is made from standard input, the "filename" set in the bytecode is <stdin>
.
>>> eval("1/0")
In addition, that code calls the ʻevalfunction, which compiles the string into bytecode. The "filename" of that bytecode is
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Should I go to bed soon?
File "<string>", line 1, in <module>
It ’s already the limit, right?
ZeroDivisionError: division by zero
This is the cause of the strange phenomenon.
At this time, the source file seems to be searched from sys.path
, so <stdin>
and < This happens if string>
is in a directory contained in sys.path
.
There was a strange error message introduced on Twitter.
For bytecode, refer to dis
module documentation.
Recommended Posts