2010-02-03 73 views
11

我使用ConfigParser在從配置文件數據來加載如下:如何從Python ConfigParser .items()中排除DEFAULT?

test.conf:

[myfiles] 
fileone: %(datadir)s/somefile.foo 
filetwo: %(datadir)s/nudderfile.foo 

load.py:

import ConfigParser 

config = ConfigParser.ConfigParser({'datadir': '/tmp'}) 
config.read('test.conf') 

print config.items('myfiles') 
print config.get('myfiles', 'datadir') 

輸出:

$ python load.py 
[('datadir', '/tmp'), ('filetwo', '/tmp/nudderfile.foo'), ('fileone', '/tmp/somefile.foo')] 
/tmp 

令人驚訝的是,變量替換('datadir', '/tmp')的默認值顯示爲的一部分。返回items().get(),就好像它們是配置文件中的值一樣。預期這種行爲?任何解決方法,以便我可以簡單地迭代.items()而沒有得到那裏的默認字典值,但仍然使用魔術插值?

參考:http://docs.python.org/library/configparser.html

謝謝!

更新:有人指出,這是預期的行爲:默認值就像配置文件中的任何其他名稱/值對一樣。同樣,在配置文件中的名稱/值對,也可用於「神奇插值」,所以如果我定義:

foo: bar 
zap: %(foo)snowl 

我會得到[... ('zap': 'barnowl')]

這是相當整潔,但我仍然想知道我能否完成我想完成的任務:在配置文件中迭代名稱/值對,並使用變量插值,而不使用默認值。

我的具體情況是這樣的:我想用類似{basedir: '/foo/bar'}的東西來初始化配置對象,因爲某些文件的絕對路徑因安裝而異。然後我需要將該配置對象傳遞給其他類並遍歷這些文件。我不希望每個讀取配置的類都必須知道它是用某些默認值初始化的,並且它應該忽略它們,因爲它們不是實際的文件。這可能嗎?任何方式來隱藏.item()和.get()的默認值,但仍然有插值?謝謝!

+2

我不能完全理解爲什麼這是默認的行爲,更不用說爲什麼沒有辦法將其關閉。 – 2014-12-22 16:33:52

回答

1

試試這個:

config = ConfigParser.ConfigParser({'blahblahblah': 'blah'}) 
config.read('test.conf') 

blahblahblah鍵也將出現在items,不是因爲它是在.ini文件的模板,而是因爲你指定它作爲默認。這是ConfigParser如何處理默認值:如果它在文件中找不到它們,它將分配它們的默認值。

因此,在我看來你在這裏有一個簡單的概念混淆。

+0

感謝您的澄清。因此默認字典用於*既提供某些鍵的默認值,也提供嵌入在配置文件中的變量的「魔術插值」。 此外,在配置文件中定義的變量也用於 「神奇插值」,所以如果我定義: FOO:酒吧 ZAP:%(富)snowl 我會[...('ZAP 「:‘barnowl’)] 這是相當整潔,但我一直在想,如果我能做到我想要完成的任務:在名稱/值對迭代在我的配置文件,與變量插值,沒有默認值。 – user264902 2010-02-03 04:36:16

4

一般來說,我發現configparser.Configparser類非常有幫助,但也缺乏。 Others have, too

然而,可以被繼承和擴展,有時很好,有時不那麼好聽(=非常依賴於實現)

這裏是你的問題的解決方案,在Python3測試:

class ConfigParser(configparser.ConfigParser): 
    """Can get options() without defaults 
    """ 
    def options(self, section, no_defaults=False, **kwargs): 
     if no_defaults: 
      try: 
       return list(self._sections[section].keys()) 
      except KeyError: 
       raise NoSectionError(section) 
     else: 
      return super().options(section, **kwargs) 

這是壞的例子之一,因爲它是部分複製的options()the source code。這將是更好,如果configparser基類RawConfigParser將提供的選項_options(self, section)內部的吸氣將納入例外投和options()這將充分利用這一點。然後,在子類中,我們可以重新使用_options()

對於Python 2,我相信唯一的變化是super()調用super(ConfigParser,self)

然後,您可以使用:

print config.options('myfiles', no_defaults=True) 

,還可以使用該列表進行迭代。

+0

你在正確的軌道上,但他被問及.items(),沒有可供選項()。不過,我認爲這會讓他在那裏。 – 2013-01-11 09:53:05

+0

我明白他的問題是如何「遍歷在我的配置文件中的名稱/值對,用變量插值,沒有默認值。」這就是上面的代碼所做的。對我來說,這是一個確切的答案。不幸的是,情況經常是這樣,問題的海報似乎並不活躍。否則,我們可以讓他決定是否可以接受答案。 – cfi 2013-01-11 12:02:17

+0

是的,這個問題依然存在,需要關注。他在代碼中使用了.items,在最後一句中使用了.item。他要求名稱/值對,這是.items所做的。選項只是返回鍵。你的回答幫助我覆蓋.items,儘管如此謝謝。 – 2013-01-12 05:03:43

2

你就不能過濾掉的默認值?

例如爲:

filtered_items = [x for x in config.items('myfiles') if x[0] not in config.defaults()]