拼写错误的__future__导入会在以后的脚本中导致错误,而不是导入位置

时间:2017-05-25 07:23:47

标签: python python-2.7 syntax python-internals

我发现了一些奇怪的东西,我在printfunction printfuncionfrom __future__ import printfunction意外拼错了print。这并没有像我预期的那样在import语句的位置给出错误,而是看起来忽略了import语句,并且当我尝试使用函数print时,随后出现了错误以与import的陈述形式不相容的方式。这使得错误的真正原因不那么明显

有人可以解释为什么错误未在#!/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') 行找到错误吗?

文件' bad_printfunc_import.py':

$ ./bad_printfunc_import.py 
  File "./bad_printfunc_import.py", line 10
    sep='\n')
       ^
SyntaxError: invalid syntax

产生错误:

print

有趣的是,如果我从文件中删除import调用,那么我确实会在$ ./bad_printfunc_import.py File "./bad_printfunc_import.py", line 3 from __future__ import printfuncion SyntaxError: future feature printfuncion is not defined 行收到错误:

__future__

对我来说,它通常会在导入失败之前报告语法错误,但是当强制执行的语法依赖于df %>% gather(var, val, -id, -group.id) %>% separate(var, c("pl.id", "well.id")) %>% spread(pl.id, val) 导入时,这就没那么有意义了。

1 个答案:

答案 0 :(得分:4)

from future ...导入是特殊的,因为它们设置了可能影响两个组件的标志:解析器和编译器。如果缺少标志,解析和编译都会失败,但解析器不会报告编译器可能会记录的拼写错误的名称。

禁用print语句是一个影响解析器的标志(连同with_statementunicode_literals标志),因此解析器只查找那些标志。因此,由于找不到print_function关键字,因此未设置禁用print语句的解析器标志,并且解析失败,这会给您语法错误。

只有在达到编译阶段时,Python才会因错误的名称而抛出语法错误:

>>> 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

理论上,解析器可以在编译器到达之前尽早报告无效的from __future__名称,但这会使解析器进一步复杂化。就目前而言,parser already manually looks for those 3 special flags,而编译器只能依赖解析的AST。必须每次都检查所有7个可能的名称会增加编译器已经捕获的错误的复杂性。