我有这个配置文件,我有统计信息:迭代次数和时间增量对象。我试图找到一种评估这个值的pythonic和安全的方法。 所以配置文件看起来像这样(test_config.cfg):
[Section]
option1 = (6, datetime.timedelta(0, 9, 520000))
option2 = (4, datetime.timedelta(0, 8, 510000))
当我使用time.timedelta()
时,RawConfigParser.set('Section', 'option', (i, t_delta))
条目就到达那里t_delta
只是两次操作之间的时间跨度,i
是迭代次数。从配置中读取此值时,它们将作为字符串返回。我想评估他们最初的情况。我尝试过的是什么,但我觉得必须有一种更安全,相应的pythonic方式:
import ConfigParser
import datetime
config = ConfigParser.RawConfigParser()
config.read('test_config.cfg')
stats = config.get('Section', 'option1')
# The obvious way is with eval() but makes me very uncomfortable using it
iterations = eval(stats)[0] # 6
duration = eval(stats)[1] # 0:00:09.520000
# The ugly way is with stripping and splitting
duration_tuple = tuple(int(i) for i in stats.split('(')[-1].strip(')').split(','))
duration = datetime.timedelta(*duration_tuple)
iterations = int(stats.split(',')[0].lstrip('('))
print iterations # 6
print duration # 0:00:09.520000
那么还有更好的方法吗?最终有没有办法在设置配置时只使用timedelta对象使用的'元组'?与(0, 9, 520000)
代替datetime.timedelta(0, 9, 520000)
一样。通过这种方式,我可以轻松使用ast.literal_eval()
。谢谢!
答案 0 :(得分:1)
使用
RawConfigParser.set('Section', 'option', (i, [t_delta.days, t_delta.seconds, t_delta.microseconds]))
您可以安排配置文件如下所示:
[Section]
option1 = [6, [0, 9, 520000]]
option2 = [4, [0, 8, 510000]]
然后你可以use json解析config.get
返回的字符串:
import ConfigParser
import datetime
import json
config = ConfigParser.RawConfigParser()
config.read('test_config.cfg')
stats = config.get('Section', 'option1')
stats = json.loads(stats)
iterations = stats[0] # 6
duration = datetime.timedelta(*stats[1]) # 0:00:09.520000
print iterations # 6
print duration # 0:00:09.520000
这与使用ast.literal_eval
基本相同。
以JSON格式解析配置文件:
但是,如果您有选项,我认为删除ConfigParser
并使用JSON
会更简单。例如,如果配置文件如下所示:
{"option2": [4, [0, 8, 510000]], "option1": [6, [0, 9, 520000]]}
然后将其读回Python,您可以使用:
import datetime
import json
with open('test_config.cfg', 'r') as f:
config = json.load(f)
stats = config['option1']
iterations = stats[0] # 6
duration = datetime.timedelta(*stats[1]) # 0:00:09.520000
print iterations # 6
print duration # 0:00:09.520000
要将配置保存为JSON格式的文件:
config = {'option': [i, [t_delta.days, t_delta.seconds, t_delta.microseconds]}
with open('test_config.json', 'w') as f:
json.dump(config, f)
答案 1 :(得分:0)
您可以将timedelta转换为秒(表示为浮点数,以便不会丢失部分秒数)。
RawConfigParser.set('Section', 'option1', '%s,%s' % (i, t_delta.total_seconds()))
现在你的部分看起来像是:
[Section]
option1 = (6, 9.520000)
option2 = (4, 8.510000)
您可以跳过使用eval:
stats = RawConfigParser.get('Section', 'option1').split(',')
iterations = int(stats[0]) # 6
duration = datetime.timedelta(seconds=float(stats[1])) # 0:00:09.520000
(编辑)
这是一个有用的示例,它将ast.literal_eval用于一个选项,并将split / cast用于另一个选项。 literal_eval风险更大,因为一个坏的演员可以运行比你想要的更多的代码,但仍然是合理的。 split / cast方法对它接受的输入要严格得多:
>>> from ConfigParser import RawConfigParser
>>> import datetime
>>> import ast
>>>
>>> i = 6
>>> t_delta = datetime.timedelta(0, 9, 520000)
>>>
>>> config = RawConfigParser()
>>> config.add_section('Section')
>>> config.set('Section', 'option_for_eval', (i, t_delta.total_seconds()))
>>> config.set('Section', 'option_for_cast', '%s,%f' % (i, t_delta.total_seconds()))
>>> config.write(open('/tmp/config.ini', 'w'))
>>>
>>> config = RawConfigParser()
>>> config.read('/tmp/config.ini')
['/tmp/config.ini']
>>> option_for_eval = config.get('Section', 'option_for_eval')
>>> option_for_eval
'(6, 9.52)'
>>> i, t_delta = ast.literal_eval(option_for_eval)
>>> i, t_delta
(6, 9.52)
>>>
>>> option_for_cast = config.get('Section', 'option_for_cast')
>>> stat = option_for_cast.split(',')
>>> i = int(stat[0])
>>> t_delta = datetime.timedelta(seconds=float(stat[1]))
>>> i, t_delta
(6, datetime.timedelta(0, 9, 520000))
>>>