2016-11-23 3079 views
2

我有一個.yaml文件,我想用Python代碼進行更新。 比方說,它看起來就像這樣:使用Python更改yaml文件中的值

state: 'present' 

我想有一個改變了狀態,並保存文件代碼。 我有這樣的嘗試和失敗:

def set_state(state): 
    with open("file_to_edit.yaml", 'rw') as f: 
     doc = yaml.load(f) 
    doc['state'] = state 
    yaml.dump(f) 

我使用的是「YAML」包爲Python。

+0

你是否收到某種錯誤? – usr2564301

+1

不,它只是沒有改變任何東西 –

+0

它只是似乎沒有寫入文件出於某種原因 –

回答

4

的問題是,yaml.dump實際上並沒有寫入文件。除非您直接將其寫入文件,否則請使用it returns the modified YAML as a string

下面應該工作:

def set_state(state): 
    with open('file_to_edit.yaml') as f: 
     doc = yaml.load(f) 

    doc['state'] = state 

    with open('file_to_edit.yaml', 'w') as f: 
     yaml.dump(doc, f) 
+1

巴姆,那就是訣竅!非常感謝! –

+0

你稱爲YAML結構是什麼? 'dump()'返回一個字符串(它包含一個YAML文檔),除非你指定'stream'參數(你應該)。將返回的字符串寫入文件是一種使用'yaml.dump()'和錯誤建議的低效率(wrt時間和內存使用)方式。 – Anthon

1

我的猜測是你沒有正確縮進,因爲你的函數在它的當前狀態似乎沒有做任何事情。 Python 確實關心縮進。

試試這個:

def set_state(state): 
    with open("file_to_edit.yaml", 'rw') as f: 
     doc = yaml.load(f) 
    doc['state'] = state 
    yaml.dump(f) 
+1

哦,不,沒有,縮進很好..我只是沒有粘貼在這裏.. –

0

你可以試試以下(它創建一個新的文件保存結果):

with open("output_file", 'a') as out: 
    with open("input_file", 'r') as f: 
     for line in f: 
      line = re.sub(r"state: present", "state: installed", line) 
      out.write(line) 
+1

我更喜歡同一個文件,但是謝謝! –

1

別的之前:從未如果你使用yaml.load()不必,因爲這樣做原則上是不安全的。對於這種簡單的結構(無標籤),您應該使用yaml.safe_load()(以及相應的safe_dump(),如果轉儲後無法安全地加載數據,則會投訴。

yaml.dump()具有以下特徵:

def dump(documents, stream=None, Dumper=Dumper, 
     default_style=None, default_flow_style=None, 
     canonical=None, indent=None, width=None, 
     allow_unicode=None, line_break=None, 
     encoding='utf-8', explicit_start=None, explicit_end=None, 
     version=None, tags=None) 

這一點只有第一個需要給予,這應該是你的doc變量。如果不指定流,則dump()將數據結構寫入內存文件對象(如StringIO),並在寫入之後將值作爲字符串返回。

因此,儘管你可以這樣做:

with open("file_to_edit.yaml", 'w') as f: 
    f.write(yaml.safe_dump(doc)) 

這是低效的,並說明如何yaml.safe_dump()作品知之甚少。

如果要打開文件進行讀寫,則必須確保重置文件中的索引並截斷其內容。這通常是不值得的努力,以便更安全重新打開文件進行寫入:

def set_state(state): 
    file_name = "file_to_edit.yaml" 
    with open(file_name) as f: 
     doc = yaml.safe_load(f) 
    doc['state'] = state 
    with open(file_name, 'w') as f: 
     yaml.safe_dump(doc, f, default_flow_style=False) 

(當然你做文件名的變量時,你要確保你覆蓋原來的,所以你不能錯打它)。

如果不指定default_flow_style=False,你的輸出就會是這樣的:

{state: deleted} 

輸出將不包括周圍present多餘的報價在你的輸入。您也可以指定default_style="'",但這也會引起state左右的報價。
如果失去引號是一個問題,你真的希望輸出看起來像輸入,你應該使用ruamel.yaml(免責聲明我是該包的作者),它可以保留單個字符串的引號,處理YAML 1.2(而不是YAML 1.1),並保留文件中的註釋。