0

I'm trying to work with json files, but I'm unable to load the file I just saved.

time_vals = { "seconds": time_spent, "day": amnt}
json_o = json.dumps(time_vals, indent = 4)

with open(os.path.join(os.getcwd(), fname + ".json",), 'a+') as f:
     loaded = json.loads(f.read()) <- error

     f.write(json_o)

I'm not sure what I'm doing wrong. I tried json.loads(f.read().decode('UTF-8')) and json.load(f) and they both give me errors as well.

Edit: The purpose of this code is to store time spent on something as a json, and if the time exceeds a certain amount add something else (that's why I'm trying to load the file, to attempt to get the int values stored)

Traceback when using json.load(f):

Traceback (most recent call last):
  File "C:\Users\julkt\PycharmProjects\pythonProject\venv\lib\site-packages\flask\app.py", line 2070, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Users\julkt\PycharmProjects\pythonProject\venv\lib\site-packages\flask\app.py", line 1515, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\Users\julkt\PycharmProjects\pythonProject\venv\lib\site-packages\flask\app.py", line 1513, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Users\julkt\PycharmProjects\pythonProject\venv\lib\site-packages\flask\app.py", line 1499, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
  File "C:/Users/julkt/Documents/Python_projectaaaaaaaaaaaaas/GUI project/guiproject.py", line 346, in send_url
    loaded = json.load(f)
  File "C:\Users\julkt\AppData\Local\Programs\Python\Python38\lib\json\__init__.py", line 293, in load
    return loads(fp.read(),
  File "C:\Users\julkt\AppData\Local\Programs\Python\Python38\lib\json\__init__.py", line 357, in loads
    return _default_decoder.decode(s)
  File "C:\Users\julkt\AppData\Local\Programs\Python\Python38\lib\json\decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "C:\Users\julkt\AppData\Local\Programs\Python\Python38\lib\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)
192.168.1.162 - - [16/Sep/2021 18:01:25] "POST /send_url HTTP/1.1" 500 -
 
9
  • Is the problem with the line you commented out? if so, uncomment then add the traceback showing the fail. a+ puts the file pointer at the end of file. If you try to read, you get nothing because you are already EOF. Rarely is "a+" the right thing in python. You'd have to reposition the file pointer to get the read to do anything useful, but the only valid thing is to seek(0) otherwise you mess up the intermediate bytes to str decoder. Commented Sep 16, 2021 at 21:58
  • Yes, the error happens with the commented out line. I'm using "a+" to be able to both write and read from the file, but if there's a better method I'm happy to use it. I edited the question with the traceback too. Commented Sep 16, 2021 at 22:02
  • Take the comment out so we can see it. In your example, you could do loaded = json.load(f). But it wouldn't work because read is already at EOF. Commented Sep 16, 2021 at 22:04
  • What is your intent with this code? It seems like you want to write multiple json records to the file. Commented Sep 16, 2021 at 22:04
  • You cant serialized datestamps but have a read of this article code-maven.com/serialize-datetime-object-as-json-in-python Commented Sep 16, 2021 at 22:06

4 Answers 4

1

When you open a file "a+" (append plus read), the file pointer is set at the end of file, ready for the next write to append data. when you read, its already at EOF so you get the empty string "". Its the same as if you had witten

json.loads("")

Its hard to manage a file for writing and reading, especially with python where an intermediate encoder/decoder for bytes to str translation may be caching data. There are other details to consider such as flushing data to make sure its really available for a read.

Better to segment your code to reading bits and writing bits, and close the file in between. To get the same sequence you've shown, you could

import json

time_vals = { "seconds": 20, "day": 44}

# load records
try:
    with open("test.json") as f:
        records = [json.loads(line) for line in f]
    print("records", records)
except OSError:
    print("no records")

# append new record
with open("test.json", "a") as f:
    print(json.dumps(time_vals), file=f) # print record with newline

Running multiple times I get

td:~/tmp/e$ python3 test.py
records [{'seconds': 20, 'day': 44}]
td:~/tmp/e$ python3 test.py
records [{'seconds': 20, 'day': 44}, {'seconds': 20, 'day': 44}]
td:~/tmp/e$ python3 test.py
records [{'seconds': 20, 'day': 44}, {'seconds': 20, 'day': 44}, {'seconds': 20, 'day': 44}]
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much! The problem stemmed from the way I was opening these files. Even with 'r+' or "w+' which should have theoretically worked did the errors persist. I guess Python's in-built functions can be tricky like that.
0

Have you tried to open the JSON with something like jsonvier to see if the JSON is properly constructed? Could be some indentation problems or similar maybe

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
0

Use json.load() for file instead of json.loads() used for strings.

From the documentation:

json.load(): Deserialize fp (a .read()-supporting text file or binary file containing a JSON document) to a Python object using this conversion table.

json.loads(): Deserialize s (a str, bytes or bytearray instance containing a JSON document) to a Python object using this conversion table.


You can split your actions in two way. First retrieve the JSON content from your file:

with open(os.path.join(os.getcwd(), fname + ".json")) as f:
    loaded = json.load(f)
# do your stuff with the loaded obj

Then write your new JSON to your file with json.dump():

with open(os.path.join(os.getcwd(), fname + ".json"), 'w') as outfile:
      json.dump(loaded, outfile)

1 Comment

I already tried that with f.read() and it gives me this error: AttributeError: 'str' object has no attribute 'read'. When I use it with just f it gives me the same error as question title.
0

When you open the file with mode "a+", you can read or write but the main idea is "append": the file pointer is placed at the end of the file, so there is nothing to read there!

Keep it simple, open the file separately for reading and writing, and you should be all right.

with open(fname + ".json", 'r') as f:
     loaded = json.load(f)

...

with open(fname + ".json", 'w') as f:
     ...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.