PyYAML在我的单元测试中显示“ ScannerError:此处不允许映射值”

时间:2018-07-20 17:37:28

标签: python-2.7 pyyaml

我正在尝试使用unittest测试许多Python 2.7类。

这里是例外:

ScannerError: mapping values are not allowed here
    in "<unicode string>", line 3, column 32:
            ... file1_with_path: '../../testdata/concat1.csv'

以下是错误消息涉及的示例:

class TestConcatTransform(unittest.TestCase):

def setUp(self):
    filename1 = os.path.dirname(os.path.realpath(__file__)) + '/../../testdata/concat1.pkl'
    self.df1 = pd.read_pickle(filename1)
    filename2 = os.path.dirname(os.path.realpath(__file__)) + '/../../testdata/concat2.pkl'
    self.df2 = pd.read_pickle(filename2)

    self.yamlconfig =  u'''
        --- !ConcatTransform
        file1_with_path: '../../testdata/concat1.csv'
        file2_with_path: '../../testdata/concat2.csv'
        skip_header_lines: [0]
        duplicates: ['%allcolumns']
        outtype: 'dataframe'
        client: 'testdata'
        addcolumn: []
    '''
    self.testconcat = yaml.load(self.yamlconfig)

出什么问题了?

我不清楚的是我拥有的目录结构是:

app
app/etl
app/tests

ConcatTransformapp/etl/concattransform.py中,而TestConcatTransformapp/tests中。通过此导入,我将ConcatTransform导入到TestConcatTransform单元测试中:

from app.etl import concattransform

PyYAML如何将该类与yamlconfig中定义的类相关联?

1 个答案:

答案 0 :(得分:1)

YAML文档可以以文档开始标记---开头,但是必须在行的开头,并且您的字符在输入的第二行缩进了八个位置。这导致---被解释为多行普通(即未加引号)标量的开始,并且在这样的标量内,您不能有:(冒号+空格)。带引号的标量只能包含:。而且,如果您的文档在根级别上没有映射或序列,而您在文档中没有,则整个文档只能包含一个标量。

如果您希望像现在一样很好地缩进资源,建议您使用dedent中的textwrap

以下内容运行无错误:

import ruamel.yaml
from textwrap import dedent

yaml_config = dedent(u'''\
        --- !ConcatTransform
        file1_with_path: '../../testdata/concat1.csv'
        file2_with_path: '../../testdata/concat2.csv'
        skip_header_lines: [0]
        duplicates: ['%allcolumns']
        outtype: 'dataframe'
        client: 'testdata'
        addcolumn: []
''')

yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_config)

您应该养成在第一个三引号的末尾加上反斜杠(\)的习惯,因此应使用YAML文档。如果这样做,您的错误实际上将指示第2行,因为文档不再以空行开头。


在加载YAML解析器期间,代码!ConcatTransform会发声。在导入过程中,对象的构造函数可能已在PyYAML加载程序中注册,并将该标签与使用PyYAML的add_constructor关联。

不幸的是,他们向默认的非安全加载程序注册了其构造函数,这不是必需的,他们可以向SafeLoader注册,因此不会迫使用户冒不受控制输入的风险。