Python文本处理和解析

Python文本处理和解析,python,parsing,Python,Parsing,我在gran/config.py中有一个文件,无法导入此文件(不是选项) 在这个config.py中,有以下代码 ...<more code> animal = dict( bear = r'^bear4x', tiger = r'^.*\tiger\b.*$' ) ...<more code> 我希望通过 grab=re.compile(“^animal\s*=\s*('.')”)或类似的东西 并且可能将tline更

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

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

...<more code>

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

...<more code>
我希望通过
grab=re.compile(“^animal\s*=\s*('.')”)
或类似的东西
并且可能将
tline
更改为
tline=filter(grab.search,text.readlines())

但它只抓取
animal=dict(
),而不抓取以下几行dict

如何获取多行?
查找动物,然后确认第一个“(”然后继续查找,直到“)?”


注意:动物dict的大小可能会改变,因此任何静态方法(如找到动物后再抓取4行)都不起作用

我不明白您到底想做什么

如果要使用正则表达式处理每一行,则在正则表达式
re.compile(“^animal\s*=\s*('.')”中有
^
。它只在
animal
位于行的开头时匹配,而不是在某些空格之后匹配。当然,它也不匹配
bear
tiger
-使用类似
re.compile(“^\s*([a-z]+)\s*=\s*('.')”

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

还要注意,text.readlines()读取行,因此
filter('not sure',text.readlines())
中的filter函数在每一行上运行,而不是在整个文件上运行。您不能在此
filter(,text.readlines())
中传递正则表达式,希望它能匹配多行

顺便说一句,使用正则表达式处理Python文件(以及HTML、XML、JSON…文件)是不明智的。对于您编写的每一个正则表达式,都会出现无法使用的情况。请使用为给定格式设计的解析器—对于Python源代码来说,它是有效的。但是对于您的用例
ast
,它太复杂了


也许最好使用经典配置文件和。更结构化的数据(如列表和目录)可以轻松地存储在或文件中。

我不明白您到底想做什么

如果要使用正则表达式处理每一行,则在正则表达式
re.compile(“^animal\s*=\s*('.')”中有
^
。它只在
animal
位于行的开头时匹配,而不是在某些空格之后匹配。当然,它也不匹配
bear
tiger
-使用类似
re.compile(“^\s*([a-z]+)\s*=\s*('.')”

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

还要注意,text.readlines()读取行,因此
filter('not sure',text.readlines())
中的filter函数在每一行上运行,而不是在整个文件上运行。您不能在此
filter(,text.readlines())
中传递正则表达式,希望它能匹配多行

顺便说一句,使用正则表达式处理Python文件(以及HTML、XML、JSON…文件)是不明智的。对于您编写的每一个正则表达式,都会出现无法使用的情况。请使用为给定格式设计的解析器—对于Python源代码来说,它是有效的。但是对于您的用例
ast
,它太复杂了


也许最好使用经典的配置文件和。更结构化的数据(如列表和目录)可以轻松地存储在或文件中。

如果不能按原样导入该文件的唯一原因是因为导入会失败,那么您可能会绕过它,而不是只处理一个非常好的Python文件文本

例如,如果我有一个名为
busted\u import.py
的文件,其中包含:

import doesnotexist

foo = 'imported!'
如果我尝试导入它,我会得到一个
ImportError
。但是如果我在尝试导入它之前使用
sys.modules
定义了
doesnotexist
模块所指的内容,导入将成功:

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

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

如果您不能按原样导入该文件的唯一原因是因为导入会失败,否则,您可能会绕过它,而不是尝试进行处理一个非常好的Python文件,仅作为文本

例如,如果我有一个名为
busted\u import.py
的文件,其中包含:

import doesnotexist

foo = 'imported!'
如果我尝试导入它,我会得到一个
ImportError
。但是如果我在尝试导入它之前使用
sys.modules
定义了
doesnotexist
模块所指的内容,导入将成功:

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

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

也许您应该尝试一些AST攻击?使用Python很容易,只需:

import ast
config= ast.parse( file('config.py').read() )
因此,要知道您有已解析的模块。您需要提取assign to
animals
并对其求值。有safe
ast.literal\u eval
函数,但由于我们调用了
dict
,因此无法在此处运行。其思想是遍历整个模块树,只留下assigns并在本地运行:

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']

使用ast hacking,您可以做更多的事情,比如访问所有If和For语句或更多。您需要检查。

也许您应该尝试一些ast hacks?使用python很简单,只是:

import ast
config= ast.parse( file('config.py').read() )
因此,要知道您有已解析的模块。您需要提取assign to
animals
并对其求值。有safe
ast.literal\u eval
函数,但由于我们调用了
dict
,它在这里无法工作。其思想是遍历整个模块树lea