【问题标题】:unexpected error parsing through json file通过json文件解析意外错误
【发布时间】:2021-05-02 11:13:22
【问题描述】:

一个小程序,从用户输入中读取名称,在 json 文件中查找名称,并根据情况问候或保存用户。如果找不到文件,则创建文件。:

import json as j
import sys
fn = 'usernames.json'


def loadnames(f):
    #load usernames to memory
    try:
        n = []
        with open(f, 'r') as fo:
            strings = j.load(fo)
            for s in strings:       #assuming that it won't be a whole string
                n.append(s)

        return n

    except FileNotFoundError:
        with open(f, 'w') as fo:
            pass
        sys.exit()

def getname():
    name = input("Name:\t")
    return name


names = loadnames(fn)
name = getname()


with open(fn, 'w') as fo:

    if name in names:
        print(f"Welcome back, {name}.")
    else:
        print(f"We don't know you, {name}. We will save you to the list.")
        names.append(name)
        for n in names:
            j.dump(n, fo)

输出(当文件存在时):

└─$ python3 rememberme.py                                                                                      1 ⨯
Traceback (most recent call last):
  File "/home/salt/Desktop/py/rememberme.py", line 57, in <module>
    names = loadnames(fn)
  File "/home/salt/Desktop/py/rememberme.py", line 42, in loadnames
    strings = j.load(fo)
  File "/usr/lib/python3.9/json/__init__.py", line 293, in load
    return loads(fp.read(),
  File "/usr/lib/python3.9/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.9/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.9/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

不确定我是否理解这个错误。这个错误是关于什么的?

【问题讨论】:

  • 可以分享一下 JSON 文件吗?
  • @charmful0x 在保存输入之前它实际上是空的

标签: python json python-3.x parsing


【解决方案1】:

您正在将文件加载为 json 文件,但在创建文件时您并未创建有效的 json 文件,空 json 文件应至少具有 {}。因此,当您尝试加载 json 时,会抱怨它期望文件中有一些有效的 json 数据。同样,您不能只在 json 文件中保留名称,它应该是键值对。做你想做的最好的方法是创建一个名称=空列表的文件,然后继续将名称附加到列表中。我对你的代码做了一些修改,让它按照你想要的方式工作。

import json as j
import sys
fn = 'usernames.json'


def loadnames(f):
    #load usernames to memory
    try:
        with open(f, 'r') as fo:
            json_file = j.load(fo)
        return json_file.get('names')

    except FileNotFoundError:
        with open(f, 'w') as fo:
            fo.write('{"names": []}')
        return []
        #sys.exit()

def getname():
    name = input("Name:\t")
    return name


names = loadnames(fn)
name = getname()


with open(fn, 'w') as fo:

    if name in names:
        print(f"Welcome back, {name}.")
    else:
        print(f"We don't know you, {name}. We will save you to the list.")
        names.append(name)
    json_file = {}
    json_file['names'] =  names
    j.dump(json_file, fo)
    fo.close()




Output ::
python3 test.py
Name:   Taj
We don't know you, Taj. We will save you to the list.

python3 test.py
Name:   Uddin
We don't know you, Uddin. We will save you to the list.

python3 test.py
Name:   Taj
Welcome back, Taj.

python3 test.py
Name:   Uddin
Welcome back, Uddin.

【讨论】:

  • return [] 有什么特殊原因吗?
  • 是的,否则程序将在“if name in names:”行崩溃,说 None 类型对象不可迭代,您必须对 None 进行特殊检查。
  • 哦,,,,好的。因此,如果loadnames() 出错,程序仍将继续结束,因为sys.exit 现在是return [][] 很快将成为names 的值,很快将在if name in names: 中进行测试。. 有道理
  • 只是添加.. return json_file.get('names') 究竟返回什么?根据link,它会返回指定一个键的值,但在这种情况下它是一个键中的多个值。它是否返回值列表?
  • get 是一个 dict 类方法,它将返回 json 字典中键“names”的任何值。在这种情况下,它将返回名称列表。
【解决方案2】:

此错误表示字符串的第一个字符不在 JSON 中。 将空字符串传递给解码时也会发生此错误。

你可以这样处理这个错误:

from json.decoder import JSONDecodeError

def loadnames(f):
    #load usernames to memory
    try:
        n = []
        with open(f, 'r') as fo:
            strings = j.load(fo)
            for s in strings:       #assuming that it won't be a whole string
                n.append(s)

        return n

    except FileNotFoundError:
        with open(f, 'w') as fo:
            pass
        sys.exit()
    
    except JSONDecodeError:
      pass

【讨论】:

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