En regardant le code source pour exceptions.c
, juste au-dessus de _set_legacy_print_statement_msg
il y a ce joli bloc de commentaire:
/* To help with migration from Python 2, SyntaxError.__init__ applies some
* heuristics to try to report a more meaningful exception when print and
* exec are used like statements.
*
* The heuristics are currently expected to detect the following cases:
* - top level statement
* - statement in a nested suite
* - trailing section of a one line complex statement
*
* They're currently known not to trigger:
* - after a semi-colon
*
* The error message can be a bit odd in cases where the "arguments" are
* completely illegal syntactically, but that isn't worth the hassle of
* fixing.
*
* We also can't do anything about cases that are legal Python 3 syntax
* but mean something entirely different from what they did in Python 2
* (omitting the arguments entirely, printing items preceded by a unary plus
* or minus, using the stream redirection syntax).
*/
Donc, il y a quelques infos intéressantes. De plus, en SyntaxError_init
méthode dans le même fichier, nous pouvons voir
/*
* Issue #21669: Custom error for 'print' & 'exec' as statements
*
* Only applies to SyntaxError instances, not to subclasses such
* as TabError or IndentationError (see issue #31161)
*/
if ((PyObject*)Py_TYPE(self) == PyExc_SyntaxError &&
self->text && PyUnicode_Check(self->text) &&
_report_missing_parentheses(self) < 0) {
return -1;
}
Notez également que les références ci-dessus, le numéro 21669 sur le python bugtracker avec une discussion entre l'auteur et Guido sur la façon d'aller à ce sujet. Ainsi nous suivons le lapin (c'est - _report_missing_parentheses
) qui est à la fin du fichier, et de voir...
legacy_check_result = _check_for_legacy_statements(self, 0);
Cependant, il existe certains cas où c'est ignorée et la normale SyntaxError
message est imprimé, voir MSeifert de réponse de plus à ce sujet. Si nous allons jusqu'à _check_for_legacy_statements
nous enfin voir le chèque pour l'héritage des instructions d'impression.
/* Check for legacy print statements */
if (print_prefix == NULL) {
print_prefix = PyUnicode_InternFromString("print ");
if (print_prefix == NULL) {
return -1;
}
}
if (PyUnicode_Tailmatch(self->text, print_prefix,
start, text_len, -1)) {
return _set_legacy_print_statement_msg(self, start);
}
Donc, pour répondre à la question: "Pourquoi n'est-ce pas Python capable de détecter le problème plus tôt?", Je dirais que le problème avec des parenthèses n'est pas ce qui est détecté; il est réellement analysée après l'erreur de syntaxe. C'est une erreur de syntaxe tout le temps, mais la pièce mineure à propos de parenthèses est pris par la suite juste pour donner un indice supplémentaire.