为什么JSONDecodeError对应于运行此特定函数的次数?

时间:2017-08-09 16:59:05

标签: python json python-3.x

提前:我为模糊的问题和长篇描述道歉。我无法为我的生活指出问题而我现在绝望了。

这是一个旨在在命令行上运行的小程序。它允许用户添加或更新条目。这些条目是字典的键值对 - 它最初是与名为info.txt的脚本位于同一级别的文本文件,必须使用" {}"进行实例化。 (糟糕的程序,我知道。我以后会解决问题)。总之,它读取文本文件,将其转换为JSON对象进行操作,然后写回文本文件。

剧本:

import os
import json
import sys


def addNew():

    with open(os.path.join(os.path.abspath(os.path.dirname(__file__)),
              "info.txt")) as entryFile:
        entryDict = json.load(entryFile)

    newEntry = sys.argv[1]
    newValue = sys.argv[2]
    confirmNew = input("Add \"{0}\" with \"{1}\" to the dictionary?"
                       "\ny or n\n".format(newEntry, newValue))

    if confirmNew == "y":
        entryDict[newEntry] = newValue
        print("You have added {} to your dictionary".format(newEntry))
    else:
        print("You have not added a new entry")

    entryString = json.dumps(entryDict)

    with open(os.path.join(os.path.abspath(os.path.dirname(__file__)),
              "info.txt"), "r+") as entryFile:
        entryFile.write(entryString)


def update():
    print("An entry with this name already exists.")

    entryFile = open(os.path.join(os.path.abspath(os.path.dirname(__file__)),                     
        "info.txt"), "r+")

    entryDict = json.load(entryFile)
    confirmUpdate = input("Update '{0}' with '{1}'?\n"
                          .format(sys.argv[1], sys.argv[2]))
    if confirmUpdate == "y":
        entryDict.update({str(sys.argv[1]): sys.argv[2]})

    entryString = json.dumps(entryDict)
    entryFile.truncate(0)
    entryFile.write(entryString)
    entryFile.close()
    print("{} has been updated.".format(sys.argv[1]))


def main():

    entryFile = open(os.path.join(os.path.abspath(os.path.dirname(__file__)),         
    "info.txt"))
    entryDict = json.load(entryFile)
    entryFile.close()

    if len(sys.argv) < 2:
        print('usage: python3 {} entry value - entry manager '
              '\nentry: name of entry and its value to add to the dict.'
              .format(sys.argv[0]))
        sys.exit()

    if len(sys.argv) == 3 and not sys.argv[1] in entryDict:
        addNew()
        sys.exit()

    if len(sys.argv) == 3 and sys.argv[1] in entryDict:
        update()
        sys.exit()


if __name__ == "__main__":
    main()

它按预期工作,直到我两次调用update()函数。换句话说,只有当我python3 file.py entryName valueHere 两次时才会出现JSONDecodeError。两次,因为根据程序,如果info.txt字典中已经存在entryName,那么它应该更新该条目。
为什么update()只能工作一次,但不能两次? 错误:raise JSONDecodeError("Expecting value", s, err.value) from None json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)指向主要功能中的entryDict = json.load(entryFile) 我尝试了load/loads"r/w/a+"的不同变体。似乎没什么用。我在做什么(主要)错了?

编辑:非常感谢任何关于通用脚本/编程的提示/技巧。

1 个答案:

答案 0 :(得分:2)

问题在于,在调用file.truncate(0)之后,您不会将新内容写入文件的开头。来自the docs

  

截形(大小=无)

     

将流大小调整为给定大小(以字节为单位)(如果未指定大小,则调整当前位置)。 当前的流位置不是   更改。此调整大小可以扩展或减少当前文件大小。在   扩展的情况下,新文件区域的内容取决于   平台(在大多数系统上,附加字节为零填充)。新的   返回文件大小。

因此,在读取,截断并写入文件之后,文件的内容看起来会像这样(其中\x00表示空字节):

\x00\x00\x00\x00\x00\x00\x00\x00{"key": "value"}

要解决此问题,请在entryFile.seek(0)之后添加entryFile.truncate(0)