评估表达式时语法无效

时间:2017-05-25 16:53:28

标签: python-3.x syntax-error

我正在

  

SyntaxError:语法无效

  

SyntaxError:无效令牌

在评估字典中的布尔表达式时

测试用例

test_expressions = ['(3530A338A58 OR 3533A500H65 OR 3533-555A57 OR 3533A593A36 OR 3533A637A60 OR 3533A636A67 OR 3533A637D30 OR 3533H370A53 OR  3533H370T63 OR 3533H693H95 OR 3533H693T57 OR 3533H873H98) AND NOT (3630H693H66 OR 3630D387A39)', 'NOT (TP(0330-000098) OR TP(0330H750A85))']

test_dict = dict((k, opt_exp_dict_clean[k]) for k in test_expressions if k in opt_exp_dict_clean)

print(test_dict)

{'(3530A338A58 OR 3533A500H65 OR 3533-555A57 OR 3533A593A36 OR 3533A637A60 OR 3533A636A67 OR 3533A637D30 OR 3533H370A53 OR  3533H370T63 OR 3533H693H95 OR 3533H693T57 OR 3533H873H98) AND NOT (3630H693H66 OR 3630D387A39)': '535A8300-503',
 'NOT (TP(0330-000098) OR TP(0330H750A85))': '336A5305-3'}

#Boolean-Normalize
opt_disp_dict_norm = {k: (True if v == "Accepted" else False) for k, v in opt_disp_dict_clean.items()}

#Replace Boolean Expressions
for expression, value in test_dict.items():
    expression = expression.replace("XOR", "is not").replace("OR", "or").replace("AND", "and").replace("NOT", "not")
    #Return Values From True Expressions
    if eval(expression, opt_disp_dict_norm):
        print(value)

返回

  File "<string>", line 1
    (3530A338A58 or 3533A500H65 or 3533-555A57 or 3533A593A36 or 3533A637A60 or 3533A636A67 or 3533A637D30 or 3533H370A53 or  3533H370T63 or 3533H693H95 or 3533H693T57 or 3533H873H98) and not (3630H693H66 or 3630D387A39)
               ^
  

SyntaxError:语法无效

'NOT (TP(0330-000098) OR TP(0330H750A85))'返回:

  File "<string>", line 1
    not (TP(0330-000098) or TP(0330H750A85))
               ^
  

SyntaxError:无效令牌

我认为这是我的术语格式的问题,因为这种方法适用于通用案例(下文)。我怎样才能使这些条款和评价友好?#34;对于python?

这些术语被称为&#34;选项&#34;这是字母数字,()-唯一的特殊字符。

通用案例:

dict1 = {'((A OR D OR E) AND F) AND NOT G': 'Pickles', '(A AND B) OR E': 'Tuna', '(NOT G) AND (A OR B OR C OR D OR E)': 'Salami'}
dict2 = {'A': 'Accepted', 'B': 'Rejected', 'C': 'Rejected', 'D': 'Accepted', 'E': 'Rejected', 'F': 'Accepted', 'G': 'Rejected', 'Z': 'Accepted'}

#Boolean-Normalize

dict2_norm = {k: (True if v == "Accepted" else False) for k, v in dict2.items()}


#Replace Boolean Expressions   
for expression, value in dict1.items():
    expression = expression.replace("XOR", "is not").replace("OR", "or")\    
    .replace("AND", "and").replace("NOT", "not") 
    #Return Values From True Expressions   
    if eval(expression, dict2_norm):    
        print(value)

返回

Pickles
Salami

编辑1

opt_exp_dict_clean非常大且来自csv文件。以下是opt_exp_dict_clean的示例:

opt_exp_dict_clean = { '(TP(2530-000580) OR TP(2530-000583) OR TP(2530-000582) OR 2530A627A05 OR 2530T652A06 OR 2530A250A38 OR 2530H633G23 OR 2530A560E37 OR 2530H636T83 OR 2530H632M38 OR 2530H636F05 OR 2530T333D72 OR 2530T723H37 OR 2530T920F60 OR 2530T983H28 OR 9800H396A37 OR 9800H396A69 OR 9800H502T33 OR 2530H632H82 OR 2530A688D82 OR 2530-003276 OR 2530-002999 OR 2530H363A37 OR 9800H502D03 OR 2530A079H59 OR 2530H335A07 OR 2530H833T37 OR 2530H635G33 OR 2530A093G52 OR 2530H632G50 OR 2530T323E83 OR 2530H508D56 OR 2530H633D08 OR 2530T323E83 OR 2530T537T29 OR 2530T333H39 OR 2530T537D03 OR 2530T323L09 OR 2530T323X30 OR 2530T593T37 OR 2530H673A30 OR 2530H637W80 OR 2530T537N65 OR 2530T537T96 OR 9800H502G93 OR 2530T806G76 OR 2530T333U72 OR 2530T882F90 OR 2530T893F63 OR 2530T920P90 OR 2530T882H68 OR 2530T920J93 OR 2530T806T99 OR 2530T806J33 OR 2530T882N32 OR 2530T537N35 OR 2530T995L50 OR 2530D305H26 OR 2530D305A80 OR 2530D360A85 OR 2530D305F33 OR 2530D362G73 OR 2530D383A32 OR 2530D360M37 OR 2530D360N26 OR 2530D603D39 OR 2530E339H37 OR 2530D6': '333A5720-85',
 'TP(0330-000099) AND NOT (2350-000233 OR 2350-000320 OR 2350A058H33 OR 3930-000322 OR 3630H693H66 OR 3630D387A39 OR 2350H693D00 OR 2350H693A33 OR TP(0330H750A85))': '232A3222-7',
 '(0330-000022 OR 0330-000029) AND NOT ((2323H299A26 AND 3363A333A30) OR 2323H372T80 OR 3930A398A60 OR 9800H396A67 OR 9800H396A86 OR 9800H396A88 OR 9800H396A89 OR 9800H396H25 OR 9800H332A26 OR 9800H332A29 OR 9800H760A20 OR 9800T858T69)': '233A3303-20',
 'TP(0330-000099) AND NOT (2533-000333 OR 2533A793H53 OR 3630H693H66 OR 3630D337A56 OR 3630D387A39 OR TP(0330H750A85))': '232A3203-2',
 '2500T803A90 AND (TP(2523-003280) OR TP(2523-003283) OR TP(2523H873A02) OR TP(2523A396H98) OR TP(2523H639A33) OR 2523T882M53 OR 2523T995J72 OR 2523D350A03 OR 2523D072E33 OR 2523D305F86) AND (2370T869A37 OR 2375T869H29 OR 2370T869A33) AND (TP(3520T372A20) OR 3520T390A32 OR 3520-000253 OR 3520D033U92) AND NOT 3520T383T88': '333A2203-333H',
 '3833-000037 AND NOT TP(0330-000098)': '337A2530-8',
 '2530-002997 OR 2530A033S00 OR 2530A053I63 OR 2530A079H63 OR 2530A093G53 OR 2530A300L37 OR 2530A289T07 OR 2530A560E38 OR 2530A560L23 OR 2530A627A03 OR 2530A688G60 OR 2530A963A32 OR 2530H373A06 OR 2530H363A36 OR 2530H637D68 OR 2530H633G33 OR 2530H633P85 OR 2530H633Z78 OR 2530H636D33 OR 2530T323L37 OR 2530T333L03 OR 2530T537F78 OR 2530T537N36 OR 2530T537T99 OR 2530T537Y00 OR 2530T652A03 OR 2530T920W00 OR 2530T920G83 OR 2530D362G09': '337A5700-28'}

opt_disp_dict_clean的示例:

opt_disp_dict_clean = {'2530T882N32': 'Accepted', 'TP(0330-000098)': 'Rejected', '2530A627A03': 'Accepted', '2530H633G33': 'Accepted', '2530A300L37': 'Rejected', '2523D072E33': 'Rejected', '3930-000322': 'Accepted', 'TP(0330-000099)': 'Rejected'}

在示例中,test_dict只是opt_exp_dict_clean

的一个子句

没有 test_dict布尔电梯会显示:

#Boolean-Normalize
opt_disp_dict_norm = {k: (True if v == "Accepted" else False) for k, v in opt_disp_dict_clean.items()}

#Replace Boolean Expressions
for expression, value in opt_exp_dict_clean.items():
    expression = expression.replace("XOR", "is not").replace("OR", "or").replace("AND", "and").replace("NOT", "not")
    #Return Values From True Expressions
    if eval(expression, opt_disp_dict_norm):
        print(value)

1 个答案:

答案 0 :(得分:0)

显然,问题在于,2530T882N32TP(0330-000098)之类的ID都不是有效的Python变量名,因此在尝试使用这些名称计算表达式时会产生语法错误。你可以替换/删除非法部分,例如使用_启动它们以使它们成为合法的变量名称,但这可能会带来名称冲突的风险,并且可能很难将它们与原始对应项关联起来。

相反,我建议您将所有这些标识符包装到d['...']中,以使它们成为用于在字典中查找的字符串。然后将带有值的字典包装到另一个相应命名的字典中,然后再将其传递到eval函数中。在替换运算符之后执行此操作并仅匹配大写字母,以便操作符(然后小写)也不会被包装。

您可以使用带有回调函数的re.sub进行替换。作为正则表达式,您可以使用例如TP\([^)]+\)|[-A-Z0-9]+。请注意,TP部分必须先行。

expression = expression.replace("XOR", "is not").replace("OR", "or").replace("AND", "and").replace("NOT", "not") 
expression = re.sub(r"TP\([^)]+\)|[-A-Z0-9]+", lambda m: "d['%s']" % m.group(), expression)
if eval(expression, {"d": opt_disp_dict_norm}):
    print(value)

但是,请注意,我仍然会收到某些ID的关键错误,而且第一个表达式缺少结束)。要处理丢失的密钥,您也可以使用"d.get('%s', True)""d.get('%s', False)"替换default values