我正在尝试创建一个脚本,您可以在其中导入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)
答案 0 :(得分:2)
为此,您必须自己编写完整的解析器。错误恢复只能由解析器正确实现,而不是在以后的阶段。我举一些例子说明为什么你的方法或任何其他解析后方法不起作用:
foo: | lorem
ipsom dolor: - it amet
在这里,我们启动一个文字块标量但是在与指标|
相同的行上开始内容。这是被禁止的。如果忽略第一行,您的YAML将如下所示:
ipsom dolor: - it amet
这是一个YAML错误,因为您无法在冒号后启动紧凑序列。但等等 - 这个内容最初是在一个块标量内,所以它不会导致错误!
现在让我们来看看Anthon的提议,即跳过所有行,直到上一次缩进:
foo: !!map
!!map {
lorem: &a ipsum
}
bar: *a
这里,第二个!!map
是非法的,因为一个节点可能只有一个标签。因此,从第二个!!map
开始删除所有行,直到找到与前一行(foo: ...
)行相同缩进的行:
foo: !!map
bar: *a
您收到错误消息,告知您*a
未引用锚点,因为您删除了包含锚点的行。但它也可以在没有锚点的情况下发生:
foo: {
!!str !!str lorem: ipsum
}
bar: baz
再次,删除行bar: baz
:
foo: {
bar: baz
现在你有一个无与伦比的{
。我可以继续下去。实际问题在于语言理论:如果某个字符串包含一个YAML错误,则它不是有效的YAML字符串。您无法在其中找到“其他YAML错误”,因为没有定义的位置可以继续(在源中:我应该在解析器出错后继续解析哪个字符?: at在出错之后我应该继续解析哪个州?)。
为了捕获后续错误,您需要在解析器中定义这些恢复点;您目前只是试图通过跳过内容来定义源中的恢复点,这还不够。
答案 1 :(得分:0)
WOOOT!我把它固定了!!!
Theres是一个很棒的工具,名为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])