Reputation: 3341
I discovered something odd, where I had accidentally misspelled printfunction
as printfuncion
in from __future__ import printfunction
. This didn't give me an error at the location of the import statement, as I would have expected, but rather the import statement was seemingly ignored and an error was subsequently raised when I attempted to use the function print
in a way that was incompatible with the statement form of print
. This made the true cause of the error much less obvious than it otherwise would have been
Can anyone explain why the error is not picked up at the import
line?
File 'bad_printfunc_import.py':
#!/usr/bin/env python
from __future__ import printfuncion
print('I will use the named param "sep" in this fuction call.',
'That will cause an error, as with print as a statement',
'rather than a function, these arguments will presumably be',
'interpretted as a tuple rather than function arguments,',
'and tuples can\'t have named elements.',
sep='\n')
Error produced:
$ ./bad_printfunc_import.py
File "./bad_printfunc_import.py", line 10
sep='\n')
^
SyntaxError: invalid syntax
Interestingly, if I remove the print
call from the file, then I do get the error at the import
line:
$ ./bad_printfunc_import.py
File "./bad_printfunc_import.py", line 3
from __future__ import printfuncion
SyntaxError: future feature printfuncion is not defined
It does makes sense to me that it would generally report syntax errors ahead of an import failure, but that makes much less sense when the syntax being enforced is dependent on that __future__
import!
Upvotes: 2
Views: 396
Reputation: 1122182
from future ...
imports are special in that they set flags that can affect two components: the parser and the compiler. Both parsing and compilation can fail if a flag is missing, but the parser won't report on misspelled names that the compiler might honour.
Disabling the print
statement is a flag that affects the parser (together with the with_statement
and unicode_literals
flags), so the parser looks for just those flags. As such, because there is no print_function
keyword found, the parser flag that disables the print
statement is not set, and parsing fails, which gives you the syntax error.
Only if the compilation stage is reached will Python throw a syntax error for incorrect names:
>>> compile('''from __future__ import nonsuch; parser error here''', '', 'exec')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "", line 1
from __future__ import nonsuch; parser error here
^
SyntaxError: invalid syntax
>>> compile('''from __future__ import nonsuch''', '', 'exec')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "", line 1
SyntaxError: future feature nonsuch is not defined
In theory the parser could report on invalid from __future__
names early, before the compiler gets to them, but that would complicate the parser further. As it stands, the parser already manually looks for those 3 special flags, while the compiler can just rely on the parsed AST. Having to check for all 7 possible names each time would add more complexity there for errors that are already caught by the compiler.
Upvotes: 4