我在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条线)都不会起作用
答案 0 :(得分:1)
我不知道你到底想要做什么。
如果您想使用正则表达式处理每一行,那么您在正则表达式^
中有re.compile("^animal\s*=\s*('.*')")
。它仅在animal
位于行的开头时匹配,而不是在某些空格之后。当然,它与bear
或tiger
不匹配 - 使用类似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也许会更好。列表和词汇等结构化数据可以轻松存储在JSON或YAML个文件中。
答案 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。