0

我有一个文件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 条额外的行)都行不通

4

3 回答 3

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())并希望它匹配多行。

顺便说一句,使用正则表达式处理 Python 文件(以及 HTML、XML、JSON... 文件)是不明智的。对于您编写的每个正则表达式,都存在不起作用的情况。使用为给定格式设计的解析器 - 对于 Python 源代码,它是ast。但是对于你的用例ast来说太复杂了。

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

于 2013-08-27T18:54:24.433 回答
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 文件中隔离将失败的导入并在尝试导入之前重新定义这些导入,则可以解决ImportErrors

于 2013-08-27T18:59:32.730 回答
1

也许你应该尝试一些 AST hack?使用python很容易,只需:

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

所以知道你有你解析的模块。您需要提取分配给animals并评估它。有安全的ast.literal_eval功能,但由于我们调用dict它在这里不起作用。这个想法是遍历整个模块树,只留下分配并在本地运行它:

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 语句或更多。您需要检查文档

于 2013-08-27T20:38:58.263 回答