2012-08-13 14 views
5

Yüz binlerce JSON kaydını 1MB'lık MAX veri yükleme sınırı olan bir sunucuya gönderiyorum. Kayıtlarım, birkaç yüz bayttan birkaç yüz bine kadar çok değişken boyutta olabilir. Daha sonra sunucuya gönderilir. Şu anda çalışıyor, ama bir jsonlanmış dizeye toSend sabit damping gerçekten ağır ve neredeyse% 100 çok fazla gibi görünüyor, ancak başka bir şekilde yapmak için bir yol bulamıyorum. Ayrı ayrı yeni kayıtların birleştirilmesi ve birlikte neler olacağının bir taksimi ile birlikte olur muyum?Python: Sunucuya göndermek için json dizesinin boyutunu sınırlama

Eminim bunu yapmanın daha temiz bir yolu olmalı, ama bilmiyorum.

Verilen her türlü yardım için teşekkür ederiz.


Bu

sendToServer doğru sonuç veren öğeleri göstermek için sadece bir kukla fonksiyondur (Sadece netlik ve tamamlanması için gönderme, aşağıda @rsegal aynı zamanda onunla geldi, şimdi kullanıyorum cevaptır),

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) 

cevap

2

aşağıdaki gibi bir şey yapacağını: En çözümü ile

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 

sorunu, Big-o açıdan büyük değil olmasıdır. Benimki lineer zamanda koşuyor, seninki ikinci dereceden geçiyor, çünkü her döngüden kümülatif uzunluğu kontrol ediyorsun. PostData'nın her seferinde sıfırlanması da çok verimli değil.

+1

HA! Etrafta oynarken, neredeyse aynı çözümde neredeyse var. Sınırın üzerinde boyut gönderecek ve 'toSendLength', 'len (json.dumps (toSend)') - len (",") 've' tentativeLength 'olmalıdır. 'len (json.dumps (row)) + len (",") çünkü her yeni satırda bir virgül ve boşluk da eklenecektir. Teşekkürler rsegal! – seaders

+0

Ve aslında bunun üstüne, her iki json dökümüne "biraz daha değerli verilerden tasarruf etmek için" separators = (',', ':') "ekledim! – seaders

+0

Bu senin için çalışmış sevindim! Python'un JSON ile olan ilişkilerinin ayrıntılarını benden daha iyi biliyorsunuz. Tekrar ilerleme kaydediyor gibi görünüyorsun ve belki de bu gelecekte birilerine yardım edecek. Süper havalı! – rsegal

İlgili konular