In einem Verzeichnis auf einem Computer habe ich "eval (" 1/0 ")" in interaktivem Python (CPython) eingegeben.
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>
Soll ich bald ins Bett gehen?
File "<string>", line 1, in <module>
Es ist schon die Grenze, oder?
ZeroDivisionError: division by zero
Ich sehe einen Laufzeitfehler mit Nullteilung, der wie erwartet ist. Aber, „Warum gehst du nicht bald ins Bett?" „Es ist schon die Grenze." Was ist das?
Python auf diesem Computer wurde nicht geändert, ebenso wie Standardbibliotheken. Es wurde kein Programm geschrieben, das dieses Phänomen verursacht. Was könnte die Ursache sein?
Entfernen Sie sich mit seltsamen Meldungen vom Computer und überprüfen Sie die Art des Tracebacks, der angezeigt wird, wenn ein Fehler auftritt. Versuchen Sie zunächst, die Quelldatei "hello.py" auszuführen, die eine Nullteilung verursacht.
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 zeigt, dass der Fehler in der Zeile "print (1/0)" aufgetreten ist. Dies ist das erwartete Verhalten.
Wie oben gezeigt, ist es praktisch, den Quellcode zu sehen, der den Fehler in Traceback verursacht hat. Da Python den Quellcode jedoch in Bytecode konvertiert und dann ausführt, enthält es den Quellcode während der Ausführung nicht. Muss.
Was ist los.
Tatsächlich liest Python den Quellcode erneut, nachdem ein Laufzeitfehler aufgetreten ist, und ruft den Code in diesem Teil ab.
Um dies zu bestätigen, habe ich hello2.py
erstellt, indem ich eine Zeile über hello.py
eingefügt habe.
hello2.py
input("Please input> ")
print(1/0)
Warten Sie auf die Eingabe mit "Eingabe", bevor die Nullteilung durchgeführt wird.
Während dieser Zeit werde ich versuchen, den Quellcode von hello2.py
selbst mit einem Editor neu zu schreiben.
Starten Sie zuerst die Ausführung und warten Sie auf die Eingabe.
$ python3 hello2.py
Please input>
Schreiben Sie die zweite Zeile mit dem entsprechenden Text neu.
hello2.py (nach dem Umschreiben)
input("Please input> ")
Bist du müde?
Geben Sie dem Prozess, der auf die Eingabe wartet, die entsprechende Eingabe und fahren Sie mit dem Prozess fort.
$ python3 hello2.py
Please input> 123[Enter]
Traceback (most recent call last):
File "hello2.py", line 2, in <module>
Bist du müde?
ZeroDivisionError: division by zero
Der Nullteilungsfehler, der mit dem Code "print (1/0)" hätte auftreten sollen, aber Traceback zeigte den umgeschriebenen Text "Sind Sie müde?" An. Sie können sehen, dass der Quellcode nach dem Auftreten des Fehlers geladen wurde.
Was aber, wenn bei der Standardeingabe oder der Ausführung von Zeichenfolgen ein Fehler auftritt? Der Code wird nicht in einer Datei gespeichert, sodass nach dem Auftreten des Fehlers nichts mehr zu lesen ist. Geben wir Python die Standardeingabe "hello.py".
$ python3 < hello.py
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
Es wird angezeigt, dass es sich um die erste Zeile von
$ python3 -c 'print(1/0)'
Traceback (most recent call last):
File "<string>", line 1, in <module>
ZeroDivisionError: division by zero
In ähnlicher Weise wird angezeigt, dass es sich um die erste Zeile von "
Im obigen Traceback gab es Hinweise wie "Datei"
Dateiname Das Argument muss die Datei angeben, aus der der Code gelesen wird, und einen erkennbaren Wert übergeben, es sei denn, er wird aus der Datei gelesen ("
" wird häufig verwendet. Masu).
Es gibt.
Wenn keine Quelldatei vorhanden ist, wird die Zeichenfolge, die den Ursprung des Quellcodes angibt, als "Dateiname" festgelegt.
Wenn Python beim Ausführen des Bytecodes auf einen Fehler stößt, vertraut es dem hier angegebenen "Dateinamen", um einen Traceback zu erstellen.
Da Dateien wie "
Aber gibt es absolut keine Dateien wie "
$ ls
<stdin> <string>
$ cat '<stdin>'
Soll ich bald ins Bett gehen?
$ cat '<string>'
Es ist schon die Grenze, oder?
Da die Eingabe in den interaktiven Modus von Python über die Standardeingabe erfolgt, lautet der im Bytecode festgelegte "Dateiname" "
>>> eval("1/0")
Zusätzlich ruft der Code die Funktion "eval" auf, die die Zeichenfolge in Bytecode kompiliert.
Der "Dateiname" dieses Bytecodes lautet "
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Soll ich bald ins Bett gehen?
File "<string>", line 1, in <module>
Es ist schon die Grenze, oder?
ZeroDivisionError: division by zero
Dies ist die Ursache für das seltsame Phänomen.
Zu diesem Zeitpunkt scheint die Quelldatei von sys.path
durchsucht zu werden, also<stdin>
und< Dies passiert, wenn sich string>
in einem Verzeichnis befindet, das in sys.path
enthalten ist.
Es gab eine seltsame Fehlermeldung auf Twitter eingeführt.
Informationen zum Bytecode finden Sie in der Dokumentation zum dis
-Modul.
Recommended Posts