Dans un répertoire sur une machine, j'ai tapé ʻeval ("1/0") ʻen Python interactif (CPython).
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>
Dois-je me coucher bientôt?
File "<string>", line 1, in <module>
C'est déjà la limite, non?
ZeroDivisionError: division by zero
Je vois, une erreur d'exécution avec zéro division, ce qui est comme prévu. Mais, "Pourquoi n'allez-vous pas vous coucher bientôt?" "C'est déjà la limite." Qu'est-ce que c'est?
Python sur cette machine n'a pas été modifié, tout comme les bibliothèques standard. Aucun programme n'a été écrit pour provoquer ce phénomène. Quelle pourrait-être la cause?
Éloignez-vous de la machine avec des messages étranges et vérifiez la nature de Traceback qui s'affiche lorsqu'une erreur se produit.
Tout d'abord, essayez d'exécuter le fichier source hello.py
qui provoque une division nulle.
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
Le traçage montre que l'erreur s'est produite sur la ligne «print (1/0)». C'est le comportement attendu.
Comme indiqué ci-dessus, il est pratique de voir le code source qui a causé l'erreur dans Traceback, mais comme Python convertit le code source en code octet puis l'exécute, il ne contient pas le code source pendant l'exécution. doit.
Que se passe-t-il.
En fait, Python lit à nouveau le code source après une erreur d'exécution et obtient le code dans cette partie.
Pour confirmer cela, j'ai créé hello2.py
en ajoutant une ligne au-dessus de hello.py
.
hello2.py
input("Please input> ")
print(1/0)
Attend une entrée à «entrée» avant que la division par zéro ne soit effectuée.
Pendant ce temps, je vais essayer de réécrire le code source de hello2.py
lui-même avec un éditeur.
Commencez par démarrer l'exécution et attendez l'entrée.
$ python3 hello2.py
Please input>
Réécrivez la deuxième ligne avec le texte approprié.
hello2.py (après réécriture)
input("Please input> ")
Êtes-vous somnolent?
Donnez une contribution appropriée au processus en attendant l'entrée et poursuivez le processus.
$ python3 hello2.py
Please input> 123[Enter]
Traceback (most recent call last):
File "hello2.py", line 2, in <module>
Êtes-vous somnolent?
ZeroDivisionError: division by zero
L'erreur de division zéro qui aurait dû se produire avec le code print (1/0)
, mais Traceback a affiché le texte réécrit, "Êtes-vous somnolent?"
Vous pouvez voir que le code source a été chargé après l'erreur.
Mais que se passe-t-il si une erreur se produit lors de l'entrée standard ou de l'exécution d'une chaîne?
Le code n'est pas enregistré dans un fichier, il n'y a donc rien à lire après l'erreur.
Donnons à Python le hello.py
comme entrée standard.
$ python3 < hello.py
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
Il s'agit de la première ligne de «
$ python3 -c 'print(1/0)'
Traceback (most recent call last):
File "<string>", line 1, in <module>
ZeroDivisionError: division by zero
De même, il s'agit de la première ligne de `
Dans le Traceback ci-dessus, il y avait des indications telles que File" <stdin> "
et File" <string> "
. Qu'est-ce que c'est?
Dans documentation de la fonction de compilation,
filename L'argument doit donner le fichier à partir duquel le code est lu; passer une valeur reconnaissable à moins qu'elle ne soit lue à partir du fichier (``
'' est couramment utilisé. Masu).
Il y a.
S'il n'y a pas de fichier source, la chaîne de caractères indiquant l'origine du code source est définie comme "nom de fichier".
Si Python rencontre une erreur lors de l'exécution du bytecode, il fera confiance au "nom de fichier" spécifié ici pour créer un Traceback.
Étant donné que les fichiers tels que «
Mais n'y a-t-il absolument aucun fichier comme «
$ ls
<stdin> <string>
$ cat '<stdin>'
Dois-je me coucher bientôt?
$ cat '<string>'
C'est déjà la limite, non?
Puisque l'entrée en mode interactif de Python se fait à partir de l'entrée standard, le "nom de fichier" défini dans le code d'octet est <stdin>
.
>>> eval("1/0")
De plus, le code appelle la fonction ʻeval`, qui compile la chaîne en bytecode. Le "nom de fichier" de ce code d'octet est «<chaîne>». Lorsqu'une erreur se produit, Python approuve ces "noms de fichiers" et crée un Traceback, de sorte que la première ligne de chaque fichier préparé s'affiche.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Dois-je me coucher bientôt?
File "<string>", line 1, in <module>
C'est déjà la limite, non?
ZeroDivisionError: division by zero
C'est la cause du phénomène étrange.
À ce stade, le fichier source semble être recherché à partir de sys.path
, donc<stdin>
et < Cela se produit si string> ʻest dans un répertoire contenu dans
sys.path`.
Il y avait un étrange message d'erreur introduit sur Twitter.
Pour le code d'octet, reportez-vous à la documentation du module dis
.
Recommended Posts