如何判断单行python是否在语法上有效?

时间:2016-05-03 19:37:18

标签: python validation

与此非常相似:

How to tell if a string contains valid Python code

唯一的区别在于,而不是完全给出整个程序,我一次只对一行代码感兴趣。

正式地说,我们说python的一行是#34;语法上有效"如果存在任何使用该特定行的语法上有效的python程序。

例如,我想将它们识别为语法上有效的行:

for i in range(10):

x = 1

因为可以在一些语法上有效的python程序中使用这些行。

我想将这些行标识为语法上无效的行:

for j in range(10 in range(10(

x =++-+ 1+-

因为没有语法上正确的python程序可以使用这些行

检查不需要太严格,只需要足够好来过滤掉明显的虚假陈述(如上所示)。当然,该行以字符串形式给出。

2 个答案:

答案 0 :(得分:13)

这使用codeop.compile_command来尝试编译代码。这与code模块does确定是否要求另一行或因语法错误而立即失败的逻辑相同。

import codeop
def is_valid_code(line):
    try:
        codeop.compile_command(line)
    except SyntaxError:
        return False
    else:
        return True

可以按如下方式使用:

>>> is_valid_code('for i in range(10):')
True
>>> is_valid_code('')
True
>>> is_valid_code('x = 1')
True
>>> is_valid_code('for j in range(10 in range(10(')
True
>>> is_valid_code('x = ++-+ 1+-')
False

我肯定在这一点上,你说的是“给出了什么?for j in range(10 in range(10(应该无效!”这一行的问题在于10()在技​​术上语法有效,至少根据Python解释器。在REPL中,你得到了这个:

>>> 10()
Traceback (most recent call last):
  File "<pyshell#22>", line 1, in <module>
    10()
TypeError: 'int' object is not callable

请注意这是TypeError不是 a SyntaxErrorast.parse表示它也有效,只是将其视为一个函数为ast.Num的调用。

这些东西在它们实际运行之前不易被捕获。 如果某种怪物设法修改了缓存的10值的值(技术上可行),您可以10()。语法仍然允许它。

不平衡的括号怎么样?这符合与for i in range(10):相同的账单。此行本身无效,但可能是多行表达式中的第一行。例如,请参阅以下内容:

>>> is_valid_code('if x ==')
False
>>> is_valid_code('if (x ==')
True

第二行是True,因为表达式可以像这样继续:

if (x ==
    3):
    print('x is 3!')

表达式完成。实际上,codeop.compile_command通过返回代码对象来区分这些不同的情况,如果它是一个有效的自包含行,None如果该行应该继续进行完整表达式,并抛出{{1}在无效的行上。

然而,您也可能遇到比最初陈述的更复杂的问题。例如,考虑行SyntaxError。如果它是模块的开头,或者前一行是),则它无效。但是,如果前一行是{,则它完全有效。

如果您只是向前工作,此处给出的解决方案将起作用,并将前一行附加为上下文,这是交互式会话的code模块does。创建能够始终准确识别单行可能可能存在于Python文件中而不考虑周围行的内容将非常困难,因为Python语法以非平凡的方式与换行符交互。这个答案回应一个给定的行是否可以在模块的开头并继续到下一行而不会失败。

最好确定识别单行的目的是什么,并以不同的方式解决问题,而不是试图为每种情况解决这个问题。

答案 1 :(得分:-1)

我只是在暗示,不确定是否会开始工作......但也许有exectry-except的某些内容?

code_line += "\n" + ("\t" if code_line[-1] == ":" else "") + "pass"
try:
    exec code_line
except SyntaxError:
    print "Oops! Wrong syntax..."
except:
    print "Syntax all right"
else:
    print "Syntax all right"

简单的行应该会得到合适的答案