用Python编写快速解析器
我写了一个用纯Python做的递归解析器,专门用来处理我们在一节课上用到的一种文件格式(ARFF)。现在运行我的作业提交时速度非常慢。经过调查发现,最耗时的就是我的解析器。它消耗了大量的CPU时间,而硬盘并不是瓶颈。
我想知道在Python中有没有更高效的写解析器的方法?我不想把它重写成C语言。我尝试过使用jython,但性能下降得很厉害!我解析的文件有的非常大(超过150MB),而且行也很长。
我现在的解析器只需要看一个字符的前瞻。我本来想在这里贴出源代码,但我不知道这样是否合适。毕竟提交的截止日期还没有到。不过,这次作业的重点并不是解析器。你可以选择任何你想用的语言,而且Java已经有一个解析器了。
注意:我使用的是x86_64系统,所以psyco(看起来PyPy也不行)都不适用。
更新:我现在把我的解析器/写入器上传到了bitbucket。
2 个回答
我给出的最基本建议是,尽量一次性把整个文件或者至少大部分内容读入内存。你不想一个字符一个字符地去读,也不想到处寻找。无论后台是怎么处理的,把整个文件放在内存里会更方便,这样你可以随意操作。
我在Python中写过解析器,实际上它们并不比其他语言写的解析器慢。很多时候,问题出在你做了不必要的工作。比如,创建、销毁再重新创建同一个对象,这样的操作比把它存起来要耗费更多资源。反复计算同一个值也比存起来要麻烦得多,等等。
在Python中,一个常见的误区是做了很多不必要的字符串操作。不要一个字符一个字符地拼接字符串;在构建你的“标记”时,应该在“主”字符串上进行操作,然后一次性提取出标记。(换句话说,先找到“主”字符串的开始和结束位置,然后用token = master[start:end]
来获取它。)一个字符一个字符地拼接字符串会让你的程序变得很慢。如果你真的需要用for c in master: newstr += c
这种方式,可能更好的办法是先把字符放到一个列表里,然后用newstr = ''.join(newstr_charlist)
来合并它们。