Python文本处理和解析

时间:2013-08-27 18:34:18

标签: python parsing

我在gran/config.py中有一个文件,我无法导入此文件(不是选项)。

在这个config.py中,有以下代码

...<more code>

    animal = dict(
        bear = r'^bear4x',
        tiger = r'^.*\tiger\b.*$'
    )

...<more code>

我希望能够根据熊或老虎来解析r'^bear4x'r'^.*\tiger\b.*$'

我从

开始
try:
    text = open('gran/config.py','r')
    tline = filter('not sure', text.readlines())
    text.close()
except IOError, str:
    pass

我希望通过
获取整个动物词典 grab = re.compile("^animal\s*=\s*('.*')")或类似的东西 并且可能会将tline更改为tline = filter(grab.search,text.readlines())

但它只抓取animal = dict(而不是下面的dict行。

我怎样才能抓住多条线? 找动物然后确认第一个'('然后继续看直到')'??

注意:动物字典的大小可能会改变,所以任何静态方法(如找到动物后再抓4条线)都不会起作用

3 个答案:

答案 0 :(得分:1)

我不知道你到底想要做什么。

如果您想使用正则表达式处理每一行,那么您在正则表达式^中有re.compile("^animal\s*=\s*('.*')")。它仅在animal位于行的开头时匹配,而不是在某些空格之后。当然,它与beartiger不匹配 - 使用类似re.compile("^\s*([a-z]+)\s*=\s*('.*')")的内容。

如果您想使用单个正则表达式处理多行, 阅读re.DOTALL和re.MULTILINE以及它们如何影响匹配换行符:

http://docs.python.org/2/library/re.html#re.MULTILINE

另请注意text.readlines()读取行,因此filter('not sure', text.readlines())中的过滤函数在每一行上运行,而不是在整个文件上运行。您无法在此filter(<re here>, text.readlines())中传递正则表达式,并希望它匹配多行。

BTW使用正则表达式处理Python文件(以及HTML,XML,JSON ...文件)并不明智。对于您编写的每个正则表达式,都存在无效的情况。使用为给定格式设计的解析器 - 对于Python源代码ast。但是对于您的用例ast太复杂了。

使用经典配置文件和configparser也许会更好。列表和词汇等结构化数据可以轻松存储在JSONYAML个文件中。

答案 1 :(得分:1)

如果您无法按原样导入该文件的唯一原因是因为导入会失败,否则您可能会破坏它,而不是试图将完美的Python文件作为文本处理。

例如,如果我有一个名为busted_import.py的文件:

import doesnotexist

foo = 'imported!'

我尝试导入它,我会得到ImportError。但是,如果我在尝试导入之前使用doesnotexist 定义sys.modules模块引用的内容,则导入将成功:

>>> import sys
>>> sys.modules['doesnotexist'] = ""
>>> import busted_import
>>> busted_import.foo
'imported!'

因此,如果您可以在Python文件中隔离将失败的导入并在尝试导入之前重新定义这些导入,那么您可以解决ImportError s

答案 2 :(得分:1)

也许你应该尝试一些AST黑客攻击?使用python很简单,只需:

import ast
config= ast.parse( file('config.py').read() )

所以知道你有解析的模块。您需要提取分配给animals并进行评估。有安全的ast.literal_eval功能但是因为我们打电话给dict它不会在这里工作。我的想法是遍历整个模块树,只留下指定并运行它localy:

class OnlyAssings(ast.NodeTransformer):

    def generic_visit( self, node ):
        return None  #throw other things away

    def visit_Module( self, node ):
        #We need to visit Module and pass it
        return ast.NodeTransformer.generic_visit( self, node )

    def visit_Assign(self, node):
        if node.targets[0].id == 'animals': # this you may want to change
            return node #pass it
        return None # throw away

config= OnlyAssings().visit(config)

编译并运行:

exec( compile(config,'config.py','exec') )
print animals 

如果动物应该在某个词典中,请将其作为本地传递给exec

data={}
exec( compile(config,'config.py','exec'), globals(), data )
print data['animals']

除了访问所有If和For语句或更多内容之外,您还可以执行更多操作。您需要检查documentation