2012-08-13 10 views
5

Estoy publicando cientos de miles de registros JSON en un servidor que tiene un límite máximo de carga de datos de 1MB. Mis registros pueden ser de tamaño muy variable, desde unos pocos cientos de bytes hasta unos cientos de miles.Python: Limitar el tamaño de una cadena json para publicar en un servidor

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) 

Que luego se publica en el servidor. Actualmente funciona, pero el vertido constante de enviar a una cadena jsonificada parece muy pesado y casi un 100% demasiado, aunque parece que no puedo encontrar otra forma de hacerlo. ¿Estaría bien si tuviera que codificar los nuevos registros individuales y llevar un recuento de lo que serían juntos?

Estoy seguro de que debe haber una manera más clara de hacerlo, pero simplemente no lo sé.

Gracias por toda la ayuda brindada.


Esta es la respuesta que yo estoy usando ahora, se me ocurrió que, al mismo tiempo que @rsegal continuación, la simple publicación de la claridad y la finalización (sendToServer es sólo una función ficticia para mostrar las cosas están funcionando correctamente),

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) 

Respuesta

2

que haría algo como lo siguiente:

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 

el problema con su solución es que no está muy bien desde una perspectiva de Big-O. La mía se ejecuta en tiempo lineal, la tuya se ejecutaría en tiempo cuadrático, porque estás verificando la longitud acumulada en cada ciclo. Restablecer postData cada vez no es muy eficiente tampoco.

+1

HA! Mientras jugaba, obtuve prácticamente la misma solución. Tengo una lista de 'restos' que toma cualquier cosa que envíe el tamaño por encima del límite y el 'toSendLength' debe ser 'len (json.dumps (toSend)) - len (",")' y el 'tentativeLength' debe ser 'len (json.dumps (row)) + len (",") porque con cada nueva fila, también se agregará una coma y espacio. Gracias rsegal! – seaders

+0

Y, en realidad, además de eso, agregué "separators = (',', ':')" a ambos volcados json, ¡guardando un poco más de datos valiosos! – seaders

+0

¡Me alegro de que funcionó para ti! Usted claramente sabe más que yo sobre los detalles de las relaciones de Python con JSON. Parece que estás haciendo progresos de nuevo, y tal vez esto ayudará a alguien en el futuro. ¡Super guay! – rsegal

Cuestiones relacionadas