2014-03-18 49 views
0

我有這個配置文件,我有統計數據:迭代次數和時間增量對象。我正試圖找到評估這個值的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之間的時間跨度是迭代的次數。當從配置中讀取這些值時,它們將作爲字符串返回。我想評估他們最初的樣子。我曾嘗試和作品,但我覺得必須有這樣做的更安全,respectivelly Python的方式:

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

您可以將timedelta轉換爲秒(表示爲float,所以t帽子部分秒不會丟失)。

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有點危險,因爲壞角色可以運行比你想要的更多的代碼,但仍然是合理的。分流/鑄造法是更爲嚴格的關於什麼輸入它將接受:

>>> 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)) 
>>> 
+0

感謝't_delta.total_seconds()'的一部分,但我仍需要使用ast.literal_eval( )這是可以的,因爲float(stats [1])部分不起作用,因爲它仍然是一個字符串,所以stats [1]將是6,stats [0]將是'('。 – skamsie

+0

@HerrActress:apply'ast .literal_eval'到整個字符串:'stats = ast.literal_eval('(6,9.520000)')'。 – unutbu

+0

是的,這絕對是我在找的。謝謝。理想情況下,我也會用' ast.literal_eval'部分爲後代:) – skamsie

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 

這與使用的想法基本相同。


爲了解析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) 
+0

+1精心答案 – skamsie

相關問題