Skip to main content
 首页 » 编程设计

python之python 2.7 中的 Pyparsing setParseAction 方法抛出异常

2025年05月04日8傻小

这是 pyparsing 和 python 2.7(在 3 中工作正常)的普遍问题。总体结构是这样的:

class SomeParser(object): 
 
    def some_action(self, string, loc, tok): 
         print("action") 
 
    def gramma(self): 
          ...pyparsing gramma for some  
 
             language.... 
         some_rule = (token + token2).setParseAction(self.some_action) 
         return some_rule 
 
     def parse(self, string): 
         self.gramma().parseString(string) 
         return True 

在 python3 中 pyparsing 工作得很好,在 2.7 中我得到了

Parsing error : some_action() takes exactly 4 arguments (1 given) 

我的问题是如何让它在两个版本中都工作?

编辑:经过一些测试,我发现这是一个普遍的问题,不仅仅是类方法。

请您参考如下方法:

我想我发现了一个问题(在 friend 的帮助下),它在 pyparsing 1.5.6 及其 _trim_arity 函数中试图猜测setParseAction(func) 中的 func 接受的参数。我将其更改为:

if not _PY3K:                                                                                                                                                                
    def _trim_arity(func, maxargs=2):                                                                                                                                                  
        limit = [0]                                                                                                                                                                    
        def wrapper(*args):                                                                                                                                                            
            while 1:                                                                                                                                                                   
                try:                                                                                                                                                                   
                    return func(*args[limit[0]:])                                                                                                                                      
                except TypeError:                                                                                                                                                      
                    if limit[0] <= maxargs:                                                                                                                                            
                        limit[0] += 1                                                                                                                                                  
                        continue                                                                                                                                                       
                    raise                                                                                                                                                              
        return wrapper                                                                                                                                                                 
    else:                                                                                                                                                                                  
        def _trim_arity(func, maxargs=2):                                                                                                                                                  
            limit = maxargs                                                                                                                                                              
            def wrapper(*args):                                                                                                                                                                                                                                                                                                              
                #~ nonlocal limit                                                                                                                                                          
                while 1:                                                                                                                                                                   
                    try:                                                                                                                                                                   
                        return func(*args[limit:])                                                                                                                                         
                    except TypeError:                                                                                                                                                      
                        if limit:                                                                                                                                                          
                            limit -= 1                                                                                                                                                     
                            continue                                                                                                                                                       
                        raise                                                                                                                                                              
            return wrapper    

到:

if not _PY3K and False:                                                                                                                                                                
    def _trim_arity(func, maxargs=2):                                                                                                                                                  
        limit = [0]                                                                                                                                                                    
        def wrapper(*args):                                                                                                                                                            
            while 1:                                                                                                                                                                   
                try:                                                                                                                                                                   
                    return func(*args[limit[0]:])                                                                                                                                      
                except TypeError:                                                                                                                                                      
                    if limit[0] <= maxargs:                                                                                                                                            
                        limit[0] += 1                                                                                                                                                  
                        continue                                                                                                                                                       
                    raise                                                                                                                                                              
        return wrapper                                                                                                                                                                 
    else:                                                                                                                                                                                  
        def _trim_arity(func, maxargs=2):                                                                                                                                                  
            # limit = maxargs                                                                                                                                                              
            def wrapper(*args):                                                                                                                                                            
                limit = maxargs                                                                                                                                                            
                #~ nonlocal limit                                                                                                                                                          
                while 1:                                                                                                                                                                   
                    try:                                                                                                                                                                   
                        return func(*args[limit:])                                                                                                                                         
                    except TypeError:                                                                                                                                                      
                        if limit:                                                                                                                                                          
                            limit -= 1                                                                                                                                                     
                            continue                                                                                                                                                       
                        raise                                                                                                                                                              
            return wrapper    

不是很优雅,但我可以看到在 pyparsing 的 trunk 版本中它已经被修复了。