【问题标题】:"TypeError: list indices must be integers, not str": yaml.load_all?“TypeError:列表索引必须是整数,而不是 str”:yaml.load_all?
【发布时间】:2015-07-14 14:36:46
【问题描述】:

我要解析具有以下数据结构的 YAML 文件:

    Version: 1
    TxnCode: MPT
    MessageID: "FFH-18544-1388620740-795905"
    Recommendations: 
     - {ReqSegFlightRef: [[1,2]],TotalPriceRef: 1,PriceInfoRef: 1}
     - {ReqSegFlightRef: [[3,4,2]],TotalPriceRef: 2,PriceInfoRef: 2}
     - {ReqSegFlightRef: [[5,4,2]],TotalPriceRef: 3,PriceInfoRef: 3}
    Flights: 
     - {OpCarrier: SN,MktCarrier: SN,FlightNb: 2902,DptDate: "0109",DptTime:     "09:30",ArrTime: "11:05",DptAirport: VIE,ArrAirport: BRU}
     - {OpCarrier: SN,MktCarrier: SN,FlightNb: 243,DptDate: "0109",DptTime: "12:15",ArrTime: "17:00",DptAirport: BRU,ArrAirport: FNA}
     - {OpCarrier: OS,MktCarrier: LH,FlightNb: 6325,DptDate: "0109",DptTime: "06:30",ArrTime: "07:35",DptAirport: VIE,ArrAirport: MUC}
    Prices: 
     - {TotalPrice: 1574.14,BaseAmount: 1368.00,TotalTaxe: 206.14,TotalSurcharge: 0.00,TotalFee: 0.00}
     - {TotalPrice: 1633.57,BaseAmount: 1368.00,TotalTaxe: 265.57,TotalSurcharge: 0.00,TotalFee: 0.00}
     - {TotalPrice: 1636.57,BaseAmount: 1368.00,TotalTaxe: 268.57,TotalSurcharge: 0.00,TotalFee: 0.00}
  LFSDetails: |
    PriceInfos: 
     - {FaresRef: [1,2],Price: {Total: 1574.14},Amount: {Total: 1368.00},Taxes:  {Total: 206.14},Surcharges: {Total: 0.00},Fees: {Total: 0.00}}
     - {FaresRef: [3,4,2],Price: {Total: 1633.57},Amount: {Total: 1368.00},Taxes: {Total: 265.57},Surcharges: {Total: 0.00},Fees: {Total: 0.00}}
     - {FaresRef: [3,4,2],Price: {Total: 1636.57},Amount: {Total: 1368.00},Taxes: {Total: 268.57},Surcharges: {Total: 0.00},Fees: {Total: 0.00}}
    ListCabinRequested: []
    FareInfo: 
     - {RBD: M,FareBasis: BFFOWAT,PTC: ADT,BreakPointId: N,Availability: 9,Cabin: W,FareType: OB}
     - {RBD: B,FareBasis: BFFOWAT,PTC: ADT,BreakPointId: Y,Availability: 9,Cabin: W,FareType: OB}
     - {RBD: B,FareBasis: BFFOWAT,PTC: ADT,BreakPointId: N,Availability: 9,Cabin: M,FareType: OB}
    Currency: EUR

我有以下代码,但在第 20 行出现“TypeError:列表索引必须是整数,而不是 str”:

def yaml_load_all(iStream,iCodeFilter=None):
    for ayamldoc in yaml.load_all(iStream):
        lfsWrapper = LFSWrapper(iCodeFilter)
        lfsDetails = ayamldoc['LFSDetails'] #line 20
        if lfsDetails is not None:
            ayamldoc['LFSDetails'] = yaml.load(lfsDetails)
        lfsWrapper.loadDict(ayamldoc)
        if lfsWrapper.isValid():
            yield lfsWrapper

(我稍后会调用此方法,将 iStream 设置为 sys.stdin 以读取数据文件)。

我认为我在这里缺少一些关于数据结构或 yaml.load_all 工作方式的基本内容。

我错过了什么?

【问题讨论】:

  • 请提供完整的 Traceback。您可以编辑您的问题以添加它。
  • 请阅读并遵守PEP-0008 指南。

标签: python yaml


【解决方案1】:

我猜你正在使用 PyYaml。

load_all 用于在单个文件中加载多个 YAML 文档,因此总是返回一个列表。你只有一个文档,它映射到一个 Python 字典,所以你应该只使用 load

【讨论】:

    【解决方案2】:

    如果不是无效的 YAML 文件,您的示例很奇怪,这使得它有点猜测这里发生了什么。它是一个有问题的 YAML 文件的原因是

    LFSDetails: |
    

    与之前和之后的行相比,缩进不同(即缩进)的行。

    直到LFSDetails,YAML 文件看起来好像在顶层有一个映射。因此,最初的解决方案可能只是将LFSDetails 推入两个空格以使其与之对齐。这将导致一个空字符串作为其文字块标量(与 | 一起引入,并且您的代码似乎依赖 YAML 作为 YAML 中的文本块。所以看起来LFSDetails 后面的所有行后面的缩进是正确的。

    要显示您的错误消息,您的 YAML 文件必须以短划线(序列指示符)开头,缩进 3 个空格:

       -
        Version: 1
      LFSDetails: |
        PriceInfos:
         - {FaresRef: [1,2],Price: {Total: 1574.14},Amount: {Total: 1368.00},Taxes:  {Total: 206.14},Surcharges: {Total: 0.00},Fees: {Total: 0.00}}
    

    给出了这个错误(我去掉了不相关的中间映射条目)。然而,这会解析,但在LFSDetails ¹ 的压痕之后完全丢弃任何东西:

    import ruamel.yaml as yaml
    
    yaml_str = """\
       -
        Version: 1
      LFSDetails: |
        PriceInfos:
         - {FaresRef: [1,2],Price: {Total: 1574.14},Amount: {Total: 1368.00},Taxes:  {Total: 206.14},Surcharges: {Total: 0.00},Fees: {Total: 0.00}}
    """
    
    for data in yaml.load_all(yaml_str):
        print(data)
        print data['LFSDetails']
    

    给你:

    [{'Version': 1}]
    Traceback (most recent call last):
      File "try.py", line 54, in <module>
        print data['LFSDetails']
    TypeError: list indices must be integers, not str
    

    由于破折号,以Version: 开头的映射是序列/列表的第一个元素,然后尝试使用字符串 (LFSDetails) 访问列表元素会得到错误。

    因此,您应该首先清理您的 YAML 以使其正确。我还建议包含start of document marker (---),即使您在示例文件中只有一个文档,因为您使用的是load_all()。并摆脱额外的缩进(即从该行的第一列开始)。删除任何虚假序列开始破折号后,得到如下内容:

    import ruamel.yaml as yaml
    
    yaml_str = """\
    ---
    Version: 1
    TxnCode: MPT
    MessageID: "FFH-18544-1388620740-795905"
    Recommendations:
     - {ReqSegFlightRef: [[1,2]],TotalPriceRef: 1,PriceInfoRef: 1}
     - {ReqSegFlightRef: [[3,4,2]],TotalPriceRef: 2,PriceInfoRef: 2}
     - {ReqSegFlightRef: [[5,4,2]],TotalPriceRef: 3,PriceInfoRef: 3}
    Flights:
     - {OpCarrier: SN,MktCarrier: SN,FlightNb: 2902,DptDate: "0109",DptTime:     "09:30",ArrTime: "11:05",DptAirport: VIE,ArrAirport: BRU}
     - {OpCarrier: SN,MktCarrier: SN,FlightNb: 243,DptDate: "0109",DptTime: "12:15",ArrTime: "17:00",DptAirport: BRU,ArrAirport: FNA}
     - {OpCarrier: OS,MktCarrier: LH,FlightNb: 6325,DptDate: "0109",DptTime: "06:30",ArrTime: "07:35",DptAirport: VIE,ArrAirport: MUC}
    Prices:
     - {TotalPrice: 1574.14,BaseAmount: 1368.00,TotalTaxe: 206.14,TotalSurcharge: 0.00,TotalFee: 0.00}
     - {TotalPrice: 1633.57,BaseAmount: 1368.00,TotalTaxe: 265.57,TotalSurcharge: 0.00,TotalFee: 0.00}
     - {TotalPrice: 1636.57,BaseAmount: 1368.00,TotalTaxe: 268.57,TotalSurcharge: 0.00,TotalFee: 0.00}
    LFSDetails: |
      PriceInfos:
       - {FaresRef: [1,2],Price: {Total: 1574.14},Amount: {Total: 1368.00},Taxes:  {Total: 206.14},Surcharges: {Total: 0.00},Fees: {Total: 0.00}}
       - {FaresRef: [3,4,2],Price: {Total: 1633.57},Amount: {Total: 1368.00},Taxes: {Total: 265.57},Surcharges: {Total: 0.00},Fees: {Total: 0.00}}
       - {FaresRef: [3,4,2],Price: {Total: 1636.57},Amount: {Total: 1368.00},Taxes: {Total: 268.57},Surcharges: {Total: 0.00},Fees: {Total: 0.00}}
      ListCabinRequested: []
      FareInfo:
       - {RBD: M,FareBasis: BFFOWAT,PTC: ADT,BreakPointId: N,Availability: 9,Cabin: W,FareType: OB}
       - {RBD: B,FareBasis: BFFOWAT,PTC: ADT,BreakPointId: Y,Availability: 9,Cabin: W,FareType: OB}
       - {RBD: B,FareBasis: BFFOWAT,PTC: ADT,BreakPointId: N,Availability: 9,Cabin: M,FareType: OB}
      Currency: EUR
    """
    
    for data in yaml.load_all(yaml_str):
        lfs_data =  data['LFSDetails']
        nested_data = yaml.load(lfs_data)
        print(type(nested_data))
        print(nested_data['FareInfo'][1]['BreakPointId'])
    

    将你作为输出:

    <type 'dict'>
    Y
    

    ¹ 这是使用ruamel.yaml 完成的,我是其中的作者。它是 PyYAML 的增强版本,使用它的结果应该是相似的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多