Verwenden Sie Python, sollte ich große Daten in Array zwischenspeichern und einmal in Datei schreiben?

StackOverflow https://stackoverflow.com/questions/19839646

  •  28-07-2022
  •  | 
  •  

Frage

Ich habe die ganze Zeit über einen Gevent Powered Crawler Download -Seiten. Das Crawler übernimmt das Produzenten-Verbraucher-Muster, das ich die Warteschlange mit solchen Daten {Methode: get, url: xxxx, other_info: yjyy} füttere.

Jetzt möchte ich einige Antwort in Dateien zusammenstellen. Das Problem ist, dass ich nicht einfach öffnen und schreiben kann, wenn jede Anfrage endet, dass IO kostspielig und die Daten nicht in korrekter Reihenfolge sind.

Ich gehe davon aus, dass ich alle Anfragen nummerieren sollte, um eine Cache -Antwort in der Reihenfolge zu eröffnen, ein Greenlet zum Loop- und Zusammenbau von Dateien zu öffnen. Pseudocode kann wie folgt sein:

max_chunk=1000
data=[]
def wait_and_assemble_file(): # a loop
    while True:
        if len(data)==28:
            f= open('test.txt','a')
            for d in data:
                f.write(d)
            f.close()
        gevent.sleep(0)

def after_request(response, index): # Execute after every request ends
    data[index]=response  # every response is about 5-25k

Gibt es eine bessere Lösung? Es gibt Tausende gleichzeitige Anfragen, und ich bezweifle, dass der Speichergebrauch zu schnell oder zu viele Schleifen gleichzeitig oder etwas unerwartet wachsen kann.

Aktualisieren:

Die obigen Codes zeigen nur, wie das Abschnitt und das Schreiben von Dateidateien das Schreiben von Dateien. In der praktischen Situation gibt es vielleicht 1hundert Schleife, um das Warten zu warten, um das Cacheeinzum fertigzustellen und in verschiedene Dateien zu schreiben.

Update2

@It ninja empfehlen, das Warteschlangensystem zu verwenden, daher schreibe ich eine Alternative mit Redis:

def after_request(response, session_id, total_block_count ,index): # Execute after every request ends
    redis.lpush(session_id, msgpack.packb({'index':index, 'content':response}))  # save data to redid

    redis.incr(session_id+':count')
    if redis.get(session_id+':count') == total_block_count: # which means all data blocks are prepared
        save(session_name)


def save(session_name):
  data_array=[]
  texts = redis.lrange(session_name,0,-1)
  redis.delete(session_name)
  redis.delete(session_name+':count')
  for t in texts:
    _d = msgpack.unpackb(t)
    index = _d['index']
    content = _d['content']
    data_array[index]=content

  r= open(session_name+'.txt','w')
  [r.write(i) for i in data_array]
  r.close()

Sieht ein bisschen besser aus, aber ich bezweifle, dass es eine gute Idee ist, große Daten in Redis zu speichern, hoffe auf weitere Vorschläge!

War es hilfreich?

Lösung

So etwas kann mit einem Warteschlangensystem besser behandelt werden, anstatt dass jeder Thread seinen eigenen Dateihandler hat. Dies liegt daran, dass Sie beim Schreiben dieser Datei möglicherweise auf Rennbedingungen stoßen, da jeder Thread seinen eigenen Handler hat.

Was die Ressourcen betrifft, sollte dies nicht zu viele Ressourcen als Ihre Festplatte konsumieren, da die Informationen, die an die Datei übergeben werden, nicht äußerst groß sind (Python ist wirklich gut). Wenn dies jedoch ein Problem darstellt, kann das Lesen der Datei in den Stücken (und das proportionale Schreiben in Brocken) dieses Problem erheblich reduzieren, solange dies als Option für Datei -Uploads verfügbar ist.

Andere Tipps

Es hängt von der Größe der Daten ab. Wenn es sehr groß ist, kann es das Programm mit der gesamten Struktur im Gedächtnis verlangsamen.

Wenn der Speicher kein Problem ist, sollten Sie die Struktur im Speicher halten, anstatt ständig aus einer Datei zu lesen. Öffnen Sie immer wieder eine Datei mit Anfrage von Stimmrechten ist keine gute Lösung.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top