【问题标题】:Python: cannot read json-file with tinydbPython:无法使用 tinydb 读取 json 文件
【发布时间】:2017-12-11 16:04:38
【问题描述】:

我有以下 json 文件:

tag.tg

[{"_type": "tag", "name": "A0", "path": "Drivers\\CMSIS\\Include\\arm_math.h", "pattern": "/^    float32_t A0;          \\/**< The derived gain, A0 = Kp + Ki + Kd . *\\/$/", "typeref": "float32_t", "kind": "member", "scope": "__anond9a59aba0f08", "scopeKind": "struct"},
{"_type": "tag", "name": "A0", "path": "Drivers\\CMSIS\\Include\\arm_math.h", "pattern": "/^    q15_t A0;           \\/**< The derived gain, A0 = Kp + Ki + Kd . *\\/$/", "typeref": "q15_t", "kind": "member", "scope": "__anond9a59aba0d08", "scopeKind": "struct"},
{"_type": "tag", "name": "A0", "path": "Drivers\\CMSIS\\Include\\arm_math.h", "pattern": "/^    q31_t A0;            \\/**< The derived gain, A0 = Kp + Ki + Kd . *\\/$/", "typeref": "q31_t", "kind": "member", "scope": "__anond9a59aba0e08", "scopeKind": "struct"},
{"_type": "tag", "name": "A1", "path": "Drivers\\CMSIS\\Include\\arm_math.h", "pattern": "/^    float32_t A1;          \\/**< The derived gain, A1 = -Kp - 2Kd. *\\/$/", "typeref": "float32_t", "kind": "member", "scope": "__anond9a59aba0f08", "scopeKind": "struct"},
{"_type": "tag", "name": "A1", "path": "Drivers\\CMSIS\\Include\\arm_math.h", "pattern": "/^    q15_t A1;$/", "typeref": "q15_t", "kind": "member", "scope": "__anond9a59aba0d08", "scopeKind": "struct"},
{"_type": "tag", "name": "A1", "path": "Drivers\\CMSIS\\Include\\arm_math.h", "pattern": "/^    q31_t A1;            \\/**< The derived gain, A1 = -Kp - 2Kd. *\\/$/", "typeref": "q31_t", "kind": "member", "scope": "__anond9a59aba0e08", "scopeKind": "struct"},
{"_type": "tag", "name": "A1", "path": "Drivers\\CMSIS\\Include\\arm_math.h", "pattern": "/^    q31_t A1;           \\/**< The derived gain A1 = -Kp - 2Kd | Kd.*\\/$/", "typeref": "q31_t", "kind": "member", "scope": "__anond9a59aba0d08", "scopeKind": "struct"},
{"_type": "tag", "name": "A2", "path": "Drivers\\CMSIS\\Include\\arm_math.h", "pattern": "/^    float32_t A2;          \\/**< The derived gain, A2 = Kd . *\\/$/", "typeref": "float32_t", "kind": "member", "scope": "__anond9a59aba0f08", "scopeKind": "struct"},
{"_type": "tag", "name": "A2", "path": "Drivers\\CMSIS\\Include\\arm_math.h", "pattern": "/^    q15_t A2;$/", "typeref": "q15_t", "kind": "member", "scope": "__anond9a59aba0d08", "scopeKind": "struct"},
{"_type": "tag", "name": "A2", "path": "Drivers\\CMSIS\\Include\\arm_math.h", "pattern": "/^    q31_t A2;            \\/**< The derived gain, A2 = Kd . *\\/$/", "typeref": "q31_t", "kind": "member", "scope": "__anond9a59aba0e08", "scopeKind": "struct"},
{"_type": "tag", "name": "ABFSR", "path": "Drivers\\CMSIS\\Include\\core_cm7.h", "pattern": "/^  __IOM uint32_t ABFSR;                  \\/*!< Offset: 0x2A8 (R\\/W)  Auxiliary Bus Fault Status /", "typeref": "__IOM uint32_t", "kind": "member", "scope": "__anoncee350000a08", "scopeKind": "struct"},
{"_type": "tag", "name": "ABR", "path": "Drivers\\CMSIS\\Device\\ST\\STM32F7xx\\Include\\stm32f767xx.h", "pattern": "/^  __IO uint32_t ABR;      \\/*!< QUADSPI Alternate Bytes register,                   Address offs/", "typeref": "__IO uint32_t", "kind": "member", "scope": "__anonea3271f52708", "scopeKind": "struct"},
{"_type": "tag", "name": "ACPR", "path": "Drivers\\CMSIS\\Include\\core_cm3.h", "pattern": "/^  __IOM uint32_t ACPR;                   \\/*!< Offset: 0x010 (R\\/W)  Asynchronous Clock Prescale/", "typeref": "__IOM uint32_t", "kind": "member", "scope": "__anoncee33efc1008", "scopeKind": "struct"},
{"_type": "tag", "name": "ACPR", "path": "Drivers\\CMSIS\\Include\\core_cm4.h", "pattern": "/^  __IOM uint32_t ACPR;                   \\/*!< Offset: 0x010 (R\\/W)  Asynchronous Clock Prescale/", "typeref": "__IOM uint32_t", "kind": "member", "scope": "__anoncee3433d1008", "scopeKind": "struct"},
{"_type": "tag", "name": "ACPR", "path": "Drivers\\CMSIS\\Include\\core_cm7.h", "pattern": "/^  __IOM uint32_t ACPR;                   \\/*!< Offset: 0x010 (R\\/W)  Asynchronous Clock Prescale/", "typeref": "__IOM uint32_t", "kind": "member", "scope": "__anoncee350001008", "scopeKind": "struct"},
{"_type": "tag", "name": "ACPR", "path": "Drivers\\CMSIS\\Include\\core_sc300.h", "pattern": "/^  __IOM uint32_t ACPR;                   \\/*!< Offset: 0x010 (R\\/W)  Asynchronous Clock Prescale/", "typeref": "__IOM uint32_t", "kind": "member", "scope": "__anonccff54a21008", "scopeKind": "struct"},
{"_type": "tag", "name": "ACR", "path": "Drivers\\CMSIS\\Device\\ST\\STM32F7xx\\Include\\stm32f767xx.h", "pattern": "/^  __IO uint32_t ACR;      \\/*!< FLASH access control register,     Address offset: 0x00 *\\/$/", "typeref": "__IO uint32_t", "kind": "member", "scope": "__anonea3271f51408", "scopeKind": "struct"}
]

我检查了https://jsonlint.com/ 上的 json 文件的有效性,看起来还可以。现在,我正在尝试将 json 文件加载到 Python 中的 TinyDB 数据库中:

from tinydb import TinyDB, Query

db = TinyDB("tag.tg")
Line = Query()
result = db.search(Line.name == "ADC_CCR_DELAY_2")
print(result)

代码在第二行 db = TinyDB("tag.tg") 失败。我收到以下错误:

TypeError: 列表索引必须是整数或切片,而不是 str

我做错了什么?我完全按照 tinydb 文档 https://pypi.python.org/pypi/tinydb:

>>> from tinydb import TinyDB, Query
>>> db = TinyDB('/path/to/db.json')

注意:
我正在使用 Python 3.6.1

【问题讨论】:

    标签: python json tinydb


    【解决方案1】:

    TinyDB 需要索引表文档,而不是列表。除非您想为您的 TinyDB 编写自定义中间件,否则您必须将 JSON 修改为:

    {
      "_default":{
        "1": {"_type": "tag", "name": "A0", "path": "Drivers\\CMSIS\\Include\\arm_math.h", "pattern": "/^    float32_t A0;          \\/**< The derived gain, A0 = Kp + Ki + Kd . *\\/$/", "typeref": "float32_t", "kind": "member", "scope": "__anond9a59aba0f08", "scopeKind": "struct"},
        "2": {"_type": "tag", "name": "A0", "path": "Drivers\\CMSIS\\Include\\arm_math.h", "pattern": "/^    q15_t A0;           \\/**< The derived gain, A0 = Kp + Ki + Kd . *\\/$/", "typeref": "q15_t", "kind": "member", "scope": "__anond9a59aba0d08", "scopeKind": "struct"},
        "3": {"_type": "tag", "name": "A0", "path": "Drivers\\CMSIS\\Include\\arm_math.h", "pattern": "/^    q31_t A0;            \\/**< The derived gain, A0 = Kp + Ki + Kd . *\\/$/", "typeref": "q31_t", "kind": "member", "scope": "__anond9a59aba0e08", "scopeKind": "struct"},
        "4": {"_type": "tag", "name": "A1", "path": "Drivers\\CMSIS\\Include\\arm_math.h", "pattern": "/^    float32_t A1;          \\/**< The derived gain, A1 = -Kp - 2Kd. *\\/$/", "typeref": "float32_t", "kind": "member", "scope": "__anond9a59aba0f08", "scopeKind": "struct"},
        "5": {"_type": "tag", "name": "A1", "path": "Drivers\\CMSIS\\Include\\arm_math.h", "pattern": "/^    q15_t A1;$/", "typeref": "q15_t", "kind": "member", "scope": "__anond9a59aba0d08", "scopeKind": "struct"},
        "6": {"_type": "tag", "name": "A1", "path": "Drivers\\CMSIS\\Include\\arm_math.h", "pattern": "/^    q31_t A1;            \\/**< The derived gain, A1 = -Kp - 2Kd. *\\/$/", "typeref": "q31_t", "kind": "member", "scope": "__anond9a59aba0e08", "scopeKind": "struct"},
        "7": {"_type": "tag", "name": "A1", "path": "Drivers\\CMSIS\\Include\\arm_math.h", "pattern": "/^    q31_t A1;           \\/**< The derived gain A1 = -Kp - 2Kd | Kd.*\\/$/", "typeref": "q31_t", "kind": "member", "scope": "__anond9a59aba0d08", "scopeKind": "struct"},
        "8": {"_type": "tag", "name": "A2", "path": "Drivers\\CMSIS\\Include\\arm_math.h", "pattern": "/^    float32_t A2;          \\/**< The derived gain, A2 = Kd . *\\/$/", "typeref": "float32_t", "kind": "member", "scope": "__anond9a59aba0f08", "scopeKind": "struct"},
        "9": {"_type": "tag", "name": "A2", "path": "Drivers\\CMSIS\\Include\\arm_math.h", "pattern": "/^    q15_t A2;$/", "typeref": "q15_t", "kind": "member", "scope": "__anond9a59aba0d08", "scopeKind": "struct"},
        "10": {"_type": "tag", "name": "A2", "path": "Drivers\\CMSIS\\Include\\arm_math.h", "pattern": "/^    q31_t A2;            \\/**< The derived gain, A2 = Kd . *\\/$/", "typeref": "q31_t", "kind": "member", "scope": "__anond9a59aba0e08", "scopeKind": "struct"},
        "11": {"_type": "tag", "name": "ABFSR", "path": "Drivers\\CMSIS\\Include\\core_cm7.h", "pattern": "/^  __IOM uint32_t ABFSR;                  \\/*!< Offset: 0x2A8 (R\\/W)  Auxiliary Bus Fault Status /", "typeref": "__IOM uint32_t", "kind": "member", "scope": "__anoncee350000a08", "scopeKind": "struct"},
        "12": {"_type": "tag", "name": "ABR", "path": "Drivers\\CMSIS\\Device\\ST\\STM32F7xx\\Include\\stm32f767xx.h", "pattern": "/^  __IO uint32_t ABR;      \\/*!< QUADSPI Alternate Bytes register,                   Address offs/", "typeref": "__IO uint32_t", "kind": "member", "scope": "__anonea3271f52708", "scopeKind": "struct"},
        "13": {"_type": "tag", "name": "ACPR", "path": "Drivers\\CMSIS\\Include\\core_cm3.h", "pattern": "/^  __IOM uint32_t ACPR;                   \\/*!< Offset: 0x010 (R\\/W)  Asynchronous Clock Prescale/", "typeref": "__IOM uint32_t", "kind": "member", "scope": "__anoncee33efc1008", "scopeKind": "struct"},
        "14": {"_type": "tag", "name": "ACPR", "path": "Drivers\\CMSIS\\Include\\core_cm4.h", "pattern": "/^  __IOM uint32_t ACPR;                   \\/*!< Offset: 0x010 (R\\/W)  Asynchronous Clock Prescale/", "typeref": "__IOM uint32_t", "kind": "member", "scope": "__anoncee3433d1008", "scopeKind": "struct"},
        "15": {"_type": "tag", "name": "ACPR", "path": "Drivers\\CMSIS\\Include\\core_cm7.h", "pattern": "/^  __IOM uint32_t ACPR;                   \\/*!< Offset: 0x010 (R\\/W)  Asynchronous Clock Prescale/", "typeref": "__IOM uint32_t", "kind": "member", "scope": "__anoncee350001008", "scopeKind": "struct"},
        "16": {"_type": "tag", "name": "ACPR", "path": "Drivers\\CMSIS\\Include\\core_sc300.h", "pattern": "/^  __IOM uint32_t ACPR;                   \\/*!< Offset: 0x010 (R\\/W)  Asynchronous Clock Prescale/", "typeref": "__IOM uint32_t", "kind": "member", "scope": "__anonccff54a21008", "scopeKind": "struct"},
        "17": {"_type": "tag", "name": "ACR", "path": "Drivers\\CMSIS\\Device\\ST\\STM32F7xx\\Include\\stm32f767xx.h", "pattern": "/^  __IO uint32_t ACR;      \\/*!< FLASH access control register,     Address offset: 0x00 *\\/$/", "typeref": "__IO uint32_t", "kind": "member", "scope": "__anonea3271f51408", "scopeKind": "struct"}
      }
    }
    

    或为现有数据编写自定义“导入器”:

    import json
    import tinydb
    
    db = tinydb.TinyDB("db_storage.json")  # create a new storage for the database
    
    with open("tag.tg", "r") as f:  # open the unmodified `tag.tg`
        json_data = json.load(f)  # parse its JSON
    
    for entry in json_data:  # iterate over each entry in the `tag.tg`
        db.insert(entry)  # insert it in the DB
    

    更新:一些附加信息,虽然有点超出了这个问题的范围。

    正如我在 cmets 中所建议的那样,如果您打算使用大量记录/数据,那么使用更优化的数据库可能是一个更好的主意。如果您需要 Python 本身提供的自封装端,SQLite 不是一个糟糕的选择,但请记住,它是一个 SQL 数据库而不是文档存储,因此您需要先构建您的架构,因此基于您的数据:

    import sqlite3
    
    connection = sqlite3.connect("db_store.sqlite")  # 'connect' to the db_store.sqlite
    
    cursor = connection.cursor()  # get a cursor
    cursor.execute("""
        CREATE TABLE IF NOT EXISTS main
        (_type TEXT, name TEXT, path TEXT, pattern TEXT,
        typeref TEXT, kind TEXT, scope TEXT, scopeKind TEXT)
    """)  # create `main` table if it doesn't exist
    

    然后您可以使用与 TinyDB 类似的方法来插入您的 tag.tg JSON - 加载、解析、插入项目:

    import json
    
    # load and parse the `tag.tg`
    with open("tag.tg", "r") as f:  # open the unmodified `tag.tg`
        json_data = json.load(f)  # parse its JSON
    
    # fields that we're interested in, you can omit some if you don't want them in the DB
    fields = ("_type", "name", "path", "pattern", "typeref", "kind", "scope", "scopeKind")
    # prepare the insert query
    query = "INSERT INTO main ({}) VALUES ({})".format(",".join(fields),
                                                       ",".join(("?",) * len(fields)))
    # now let's add the records to the SQLite table:
    cursor = connection.cursor()  # get a cursor
    cursor.executemany(query, ([e.get(field, None) for field in fields] for e in json_data))
    

    现在您可以执行以下操作:

    cursor = connection.cursor()  # get a cursor
    cursor.execute("SELECT path FROM main WHERE name = 'ABFSR'")  # a generic SQL SELECT
    path, = cursor.fetchone()  # get the first result
    print("Path: " + path)  # Path: Drivers\CMSIS\Include\core_cm7.h
    

    它肯定能够处理比 TinyDB 更多的记录,唯一有问题的可能是导入您的初始 JSON 数据 - 如果您的系统无法同时处理加载和解析整个 JSON 结构,您可能想查看流式 JSON 解析器,尽管如果所有数据的结构都如您所见(每行不同的 JSON 对象),则可能会通过删除周围的 [ 和 ] 以及逗号分隔符和逐行读取和解析文件。

    【讨论】:

    • 太棒了!您的定制进口商正是我所需要的。非常感谢!
    • 一个问题......这个自定义导入器非常非常慢 - 我现在正在一个包含 20.000 行的更大数据库上尝试它,但仍在等待。你会推荐什么?
    • @K.Mulier - JSON 不完全是一种流友好格式,因此大多数解析器会加载整个文件,然后将其作为一个整体进行解析,一旦开始,这可能会花费大量时间成数千条记录。更糟糕的是,使用默认 JSON 存储的 TinyDB 会做同样的事情(更不用说在每次进行更改时序列化和写入整个 JSON 文件)——它只是没有针对这种事情进行优化。如果您擅长处理大量数据,请检查 MongoDB、Redis、Couchbase 或任何其他性能更高的 NoSQL 文档存储。
    • 谢谢。 Python 中的 sqlite3 怎么样?
    • @K.Mulier - 大量记录的更好选择,尽管它不是文档存储,因此存在限制。检查上面的更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-11
    • 2014-08-07
    • 1970-01-01
    • 1970-01-01
    • 2017-05-28
    • 2019-06-15
    相关资源
    最近更新 更多