5

最大データアップロード制限が1MBのサーバーに数十万の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)

その後、サーバーに投稿します。現在は機能していますが、jsonified文字列へのtoSendの継続的なダンプは非常に重く、ほぼ100%多すぎるようですが、別の方法を見つけることはできないようです。個々の新しいレコードを文字列化し、それらが一緒になるものの集計を維持しても大丈夫でしょうか?

これを行うにはもっとクリーンな方法があるはずですが、私にはわかりません。

与えられたすべての助けに感謝します。


これは私が現在使用している答えです。以下の@rsegalと同時に思いついたので、わかりやすく完了させるために投稿しました(sendToServerは、正常に動作していることを示すためのダミー関数です)。

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)
4

1 に答える 1

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

ソリューションの問題は、Big-Oの観点からはあまり良くないということです。ループごとに累積長をチェックしているため、鉱山は線形時間で実行され、2次時間で実行されます。毎回postDataをリセットすることも、あまり効率的ではありません。

于 2012-08-13T17:09:44.077 に答える