2012-08-13 8 views
5

MAXデータアップロード制限が1MBのサーバーに何十万個ものJSONレコードを投稿しています。私の記録は、わずか数百バイトから数百万という非常に多様なサイズにすることができます。Python:サーバーに投稿するjson文字列のサイズを制限する

def checkSize(payload): 
    return len(payload) >= bytesPerMB 


toSend = [] 
for row in rows: 
    toSend.append(row) 
    postData = json.dumps(toSend) 
    tooBig = tooBig or checkSize() 
    if tooBig: 
      sendToServer(postData) 

これがサーバーに送信されます。現在は機能していますが、toSendの継続的なダンピングは、実際には重く、ほぼ100%は重すぎるように見えますが、別の方法を見つける方法が見つからないようです。私は個々の新しい記録をストリング化し、一緒になるものを集計することで大丈夫だろうか?

これを行うクリーナーの方法が必要であると確信していますが、わかりません。

ありがとうございました。


この

はsendToServerが正しく機能している事を示すためだけのダミー関数である(私は明快さと完成を投稿、以下@rsegalと同時に、それを思い付いた、私が今使っている答えです)は、

import pickle 
import json 

f = open("userProfiles") 
rows = pickle.load(f) 
f.close() 

bytesPerMB = 1024 * 1024 
comma = "," 
appendSize = len(comma) 

def sendToServer(obj): 
    #send to server 
    pass 

def checkSize(numBytes): 
    return numBytes >= bytesPerMB 

def jsonDump(obj): 
    return json.dumps(obj, separators=(comma, ":")) 

leftover = [] 
numRows = len(rows) 
rowsSent = 0 

while len(rows) > 0: 
    toSend = leftover[:] 
    toSendSize = len(jsonDump(toSend)) 
    leftover = [] 
    first = len(toSend) == 0 

    while True: 
     try: 
      row = rows.pop() 
     except IndexError: 
      break 

     rowSize = len(jsonDump(row)) + (0 if first else appendSize) 
     first = False 

     if checkSize(toSendSize + rowSize): 
      leftover.append(row) 
      break 

     toSend.append(row) 
     toSendSize += rowSize 

    rowsSent += len(toSend) 
    postData = jsonDump(toSend) 
    print "assuming to send '{0}' bytes, actual size '{1}'. rows sent {2}, total {3}".format(toSendSize, len(postData), rowsSent, numRows) 
    sendToServer(postData) 

答えて

2

は、私は次のような何かをするだろう:あなたのソリューションと

toSend = [] 
toSendLength = 0 
for row in rows: 
    tentativeLength = len(json.dumps(row)) 
    if tentativeLength > bytesPerMB: 
     parsingBehavior // do something about lolhuge files 
    elif toSendLength + tentativeLength > bytesPerMB: // it would be too large 
     sendToServer(json.dumps(toSend)) // don\'t exceed limit; send now 
     toSend = [row] // refresh for next round - and we know it fits! 
     toSendLength = tentativeLength 
    else: // otherwise, it wont be too long, so add it in 
     toSend.append(row) 
     toSendLength += tentative 
sentToServer(json.dumps(toSend)) // if it finishes below the limit 

問題はそれがビッグOの観点から素晴らしいではないということです。 Mineは線形時間で実行されますが、ループごとに累積長をチェックしているので、2次の時間で実行されます。 postDataを毎回リセットすることはあまり効率的ではありません。

+1

HA!周りを遊んでいる間、私はまったくまったく同じ解決策に近づいてきました。私は '余分な'リストを持っています。これは、制限を超えてサイズを送信するもので、 'toSendLength'は 'len(json.dumps(toSend)) - len( "、")'で、 'tentativeLength' 'len(json.dumps(row))+ len( "、")とします。新しい行ごとにコンマとスペースも追加されるためです。ありがとうrsegal! – seaders

+0

そして実際には、私は両方のjsonダンプに「セパレータ=( '、'、 ':')」を追加して、より貴重なデータを節約しました! – seaders

+0

あなたのために働いたうれしい! PythonがJSONを扱っていることの詳細については、私よりもはっきり分かっています。あなたはもう一度進歩しているようですが、これは将来誰かを助けるでしょう。超かっこいい! – rsegal

関連する問題