2017-07-31 85 views
0

我試圖創建一個腳本,您可以在其中導入yaml文件並驗證它是否爲yaml格式。我也希望它列出文件中的每個錯誤。我想要做的是利用yaml安全加載,然後當它失敗時打印錯誤消息,忽略該行,然後重新讀取文件,並重復直到打印文件中的所有錯誤。導入文件時是否有一種簡單的方法可以忽略行列表?繼承人我現在的代碼:解析yaml文件時跳過行

#Verify YAML modules is installed 
try: 
    import yaml 
except: 
    print ('You do not have the YAML module installed.\n'+'Run: pip install yaml to fix this') 
    quit() 
#Verify argparse module is installed 
try: 
    import argparse 
except: 
    print ('You do not have the argparse module installed.\n'+'Run: pip install argparse to fix this') 
    quit() 
import itertools 
#Loop variable 
i = 0 

#Configuration for argument parsing 
parser = argparse.ArgumentParser() 
parser.add_argument("path", help='File/Directory path to be examined', type=str) 
args = (parser.parse_args()) 

#The main loop 
while (i == 0): 
    skip = [] 
    #Loop to skip lines for re-iteration 
    with open(args.path) as infile: 
     for line in itertools.islice(infile, skip, None): 
      #Verify file is in YAML, if so save as dict then end 
      try: 
       yml = yaml.load(txt, yaml.SafeLoader) 
       print yml 
       i == 1 
      #if not yaml record error seen, then redo the loop skipping previous errors 
      except yaml.YAMLError as exc: 
       print ("Error while parsing YAML file:") 
       if hasattr(exc, 'problem_mark'): 
          mark = exc.problem_mark 
          print "Error position: (%s:%s)" % (mark.line+1, mark.column+1) 
          print exc 
          skip.add(mark.line+1) 
+1

我不認爲高層次的邏輯是合理的; yaml可以通過從其中刪除一行來變得無法解析,因此您最終可能會遇到跳過該行並重新分析該文件的問題,從而無法驗證。 – cowbert

+0

嗯,那麼還有另一種方法來列出除此之外的文件中的所有yaml錯誤。我想我可以看到你的話。但讓我們說第2行和第78行有問題,用我使用的安全加載方法會顯示第2行的錯誤,然後停止。使用該腳本的用戶基本上必須運行該腳本,修復1行,運行腳本,修復另一行,這比一次修復所有錯誤需要更長的時間(如果我能弄清楚如何一次顯示它們) –

+1

@ VincentMorris您可以嘗試跳過所有行,直到找到與錯誤發生前相同的縮進級別並從此處重新啓動。這裏有一些注意事項:1)你的錯誤指示器可能指示第1行,但實際的修正是幾行前進2)SafeLoader不能加載帶有標籤的YAML 3)你使用的PyYAML有未修復的錯誤,在完美的YAML上拋出錯誤4)PyYAML仍然不支持YAML 1.2規範(從2009年開始)。 – Anthon

回答

2

爲了這個工作,你必須自己編寫完整的解析器。錯誤恢復是隻能由解析器正確執行的事情,而不是在以後的階段。我給你的,爲什麼你的方法或其他任何解析器後的做法是行不通的一些例子:

foo: | lorem 
    ipsom dolor: - it amet 

在這裏,我們開始一個文字塊標,但開始在同一行的指標|內容。這是禁止的。如果你忽略了第一線,你的YAML看起來像:

ipsom dolor: - it amet 

這是一個YAML錯誤,因爲你無法啓動冒號後的緊湊序列。但是等一下 - 這個內容最初是在塊標量內,所以它不會導致錯誤!

現在,讓我們一起去安通的建議,跳過所有行,直到前一個缺口:

foo: !!map 
    !!map { 
    lorem: &a ipsum 
    } 
bar: *a 

這裏,第二!!map是非法的,因爲一個節點可能只有一個標籤。所以,你刪除,直到你找到具有相同縮進以前(foo: ...)線路的線路從第二!!map所有行:

foo: !!map 
bar: *a 

你得到一個錯誤,告訴您*a沒有引用一個錨,因爲你刪除包含錨點的行。但它也可能發生不主播:

foo: { 
    !!str !!str lorem: ipsum 
    } 
bar: baz 

同樣,您刪除的行,直到bar: baz

foo: { 
bar: baz 

現在你有一個無與倫比的{。我可以繼續下去。實際的問題在於語言理論:如果某個字符串包含一個YAML錯誤,它不是一個有效的YAML字符串。您無法在其中找到「其他YAML錯誤」,因爲沒有定義點繼續在哪裏繼續(在源文件中:我應該繼續在解析器中解析哪個字符?應該在哪個狀態之後繼續解析錯誤?)。

爲了捕獲後續錯誤,您需要在解析器中定義那些恢復點;您目前僅嘗試通過跳過內容來定義源中的恢復點,這是不夠的。

0

WOOOT!我修好了它!!!

即使世界一個名爲Yamllint,我利用做的正是我想要的工具:

#Verify YAML modules is installed 
try: 
    import yaml 
except: 
    print ('You do not have the YAML module installed.\n'+'Run: pip install pyaml to fix this') 
    quit() 
#Verify argparse module is installed 
try: 
    import argparse 
except: 
    print ('You do not have the argparse module installed.\n'+'Run: pip install argparse to fix this') 
    quit() 

try: 
    import yamllint 
except: 
    print ('You do not have the yamllint module installed.\n'+'Run: pip install yamlint to fix this') 
    quit() 
from subprocess import call 
#call(["ls", "-l"]) 

#Configuration for argument parsing 
parser = argparse.ArgumentParser() 
parser.add_argument("path", help='File/Directory path to be examined', type=str) 
args = (parser.parse_args()) 

#The main loop 

#Verify file is in YAML, if so save as dict then end 
ignore = set([]) 
with open(args.path, "r") as f: 
    try: 
     yml = (yaml.load(f)) 
     print yml 
    #If not yaml run through yamllint 
    except yaml.YAMLError as exc: 
     call(["yamllint","-f","parsable",args.path])