iT邦幫忙

1

Python 存成JSON

需求類似如下,會跑迴圈去把需要的資料存進來

存的值可能是另一個 dictionary,說明有簡化
因為資料量比較多,想要用累加的方式逐步增加 JSON(a.json 的格式)
不過會造成結果是{}{}{}的格式錯誤

目前是採用 b.json 的方式最後才存檔,就怕愈後面暫存的資料量太大

import json

temp_all = {}

for i in range(5):
    main = i
    val = {i+1:"temp"}
    temp = {}
    temp[i] = val
    temp_all.update(temp)
    js = json.dumps(temp)
    file = open('a.json', 'a')
    file.write(js)
    file.close()

js = json.dumps(temp_all)
file = open('b.json', 'w')
file.write(js)
file.close()

a.json (格式錯誤)

{
    "0": {
        "1": "temp"
    }
}{
    "1": {
        "2": "temp"
    }
}{
    "2": {
        "3": "temp"
    }
}{
    "3": {
        "4": "temp"
    }
}{
    "4": {
        "5": "temp"
    }
}

b.json (格式正確)

{
    "0": {
        "1": "temp"
    },
    "1": {
        "2": "temp"
    },
    "2": {
        "3": "temp"
    },
    "3": {
        "4": "temp"
    },
    "4": {
        "5": "temp"
    }
}

另一個小疑問
之前用 VSCODE 開既有的 JSON 會是白字(應該是純字串,格式化文件才會是階層有顏色)
{"0":{"1":"temp"},"1":{"2":"temp"},"2":{"3":"temp"},"3":{"4":"temp"},"4":{"5":"temp"}}

但目前存出來的檔案卻直接有顏色(類似已經知道是什麼格式)
不知道為什麼會這樣?

{"0":{"1":"temp"},"1":{"2":"temp"},"2":{"3":"temp"},"3":{"4":"temp"},"4":{"5":"temp"}}
如果暫存的資料量指的是吃記憶體的話
我剛剛測試了一下
資料是使用你提供的範例 不過迴圈改成 1000 萬
一筆一筆寫入 花了一個小時
整筆寫入花了 53 秒
記憶體用量到最後是差不多的
那你覺得有差嗎
froce iT邦大師 1 級 ‧ 2020-08-12 17:55:43 檢舉
ㄜ...
真的覺得量大請存資料庫,看你是要postgres還是mongodb都好。結案。
hokou iT邦好手 1 級 ‧ 2020-08-14 11:37:48 檢舉
感謝大家的回應,因只能挑選一個最佳解答就比較抱歉
(好想選多個)

主要因過程處理較久(計算座標),沒辦法即時確認結果,才想要逐次增加 JSON 資料,如果因為 JSON 要一次性可能就沒辦法了

也感謝大家的實驗精神確認寫入的速度

JSON 顯示的部分,vscode 上右下的格式是一致的,推測是顯示上即時處理的關係,就暫時不再確認了
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
1
秋米苗
iT邦新手 5 級 ‧ 2020-08-12 09:03:34
最佳解答

JSON 的限制是必須一次讀檔,因此可能無解。
其他做法能使用 CSV 或 SQLITE 來達到資料儲存的目的。
參見 https://stackoverflow.com/questions/12994442/how-to-append-data-to-a-json-file

1
海綿寶寶
iT邦大神 1 級 ‧ 2020-08-12 09:09:15

1.資料格式正確最重要,「資料量太大」是等到碰到錯誤訊息之後再來處理,不用超前部署。你大可放心,如果真的資料量太大,別說逐步增加 json,你說不定連 {} 都不能用
2.json內容最重要(顏色不重要),如果硬要猜的話,可能是「副檔名」的原因(例:a.json 和 b.json.txt)

1
打狗松鼠
iT邦新手 4 級 ‧ 2020-08-12 10:40:36

需求類似如下,會跑迴圈去把需要的資料存進來

看Code的話可以看出你在每次迴圈就把一個temp物件給dump到a.json裡面,但你在匯出檔案時,檔案或python並不會聰明到幫你在每一個temp物件之間加上,,所以檔案格式才會是那個樣子,你可以看到每一個temp物件之間並沒有逗號做區隔。

目前是採用 b.json 的方式最後才存檔,就怕愈後面暫存的資料量太大

如海綿大所說,遇到資料量太大再去想要怎麼處理也不遲,你可以考慮諸如Firebase這種json為底的NoSQL資料庫等
b.json能成功的原因是你把所有temp物件統整至temp_all物件,python在輸出時可以認出這整個物件是被統整起來的,輸出出來的json自然就會是完整格式。

另一個小疑問
之前用 VSCODE 開既有的 JSON 會是白字(應該是純字串,格式化文件才會是階層有顏色)

注意看VSCode右下角,會有諸如「UTF-8」、「CLRF」、「JSON/純文字」等標籤
UTF-8是指你要用什麼編碼開啟檔案,CLRF是換行字元如何指定(通常CLRF是Windows才會用),JSON那邊則是VSCode會判斷你的檔案是什麼類型,進而用該類型的語法去上顏色,方便你識讀資料

你可以自己開啟python檔後去觀察這個標籤,此時應該會變更為python。

2
japhenchen
iT邦超人 1 級 ‧ 2020-08-13 08:28:20

1000萬筆交易記錄,只要 open('file.txt','w+') 追加,無需要全部讀出放DICT或LIST
如果是1000萬筆DICT,壓縮一下倒也沒剩多少,時間耗費嘛,我都敢放在樹莓派3B(沒+)上跑了,資料量約十萬筆,每筆dict都是三層結構 ...... 頂多十來秒
{'10906001':{'數學':{'第一次段考':50,'第二次段考':69} ,'國文':{...........

    def loaddict():
        with gzip.open('/home/pi/dict.gz',"rb") as gz :
            return jsonpickle.decode(gz.read().decode())

    def savedict(dict):
        with gzip.open('/home/pi/dict.gz','wb') as gz :
            gz.write(jsonpickle.encode(dict))

我要發表回答

立即登入回答