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

Eva*_* Pu 16 python validation

它与此非常相似:

如何判断字符串是否包含有效的Python代码

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

在形式上,如果存在任何使用该特定行的语法上有效的python程序,我们说python的一行是"语法上有效的".

例如,我想将这些标识为语法上有效的行:

for i in range(10):

x = 1
Run Code Online (Sandbox Code Playgroud)

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

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

for j in range(10 in range(10(

x =++-+ 1+-
Run Code Online (Sandbox Code Playgroud)

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

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

Aly*_*sen 15

这用于codeop.compile_command尝试编译代码.这是在相同的逻辑code模块确实,以确定是否要求对另一条线或立即失败,语法错误.

import codeop
def is_valid_code(line):
    try:
        codeop.compile_command(line)
    except SyntaxError:
        return False
    else:
        return True
Run Code Online (Sandbox Code Playgroud)

它可以使用如下:

>>> 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
Run Code Online (Sandbox Code Playgroud)

我确信在这一点上,你说的是"什么给出了?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
Run Code Online (Sandbox Code Playgroud)

请注意这是一个TypeError,而不是一个SyntaxError.ast.parse说它也是有效的,只是将它视为一个函数是一个调用ast.Num.

这些东西在它们实际运行之前不易被捕获.如果某种怪物设法修改缓存10值的值(技术上可行),你可能会这样做10().它仍然是语法所允许的.

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

>>> is_valid_code('if x ==')
False
>>> is_valid_code('if (x ==')
True
Run Code Online (Sandbox Code Playgroud)

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

if (x ==
    3):
    print('x is 3!')
Run Code Online (Sandbox Code Playgroud)

表达式将完整.实际上,codeop.compile_command如果代码对象是有效的自包含行,None则返回代码对象,如果预期该行继续完整表达式,并抛出SyntaxError无效行,则可以区分这些不同情况.

但是,您也可能遇到比最初声明的更复杂的问题.例如,考虑一下这条线).如果它是模块的开头,或者前一行是{,则它无效.但是,如果前一行是(1,2,,则它完全有效.

这里给出的解决方案将工作,如果你只工作着,并追加先前线作为背景,这是什么样的代码模块了一个交互式会话.创建的东西,总是能够准确地识别是否单行能可能在Python文件中存在不考虑周围线将是非常困难的,因为Python的语法与非平凡的方式换行交互.这个答案回应一个给定的行是否可以在模块的开头并继续到下一行而不会失败.

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