2016-11-07 2 views
2

Die Idee ist, N Dateien schreiben mit N Prozesse.spawn mehrere Prozesse zum Schreiben verschiedener Dateien Python

Die Daten für die Datei geschrieben werden sollen, werden aus mehreren Dateien kommen, die auf einem Wörterbuch gespeichert werden, die eine Liste als Wert hat, und es sieht wie folgt aus:

dic = {'file1':['data11.txt', 'data12.txt', ..., 'data1M.txt'], 
     'file2':['data21.txt', 'data22.txt', ..., 'data2M.txt'], 
     ... 
     'fileN':['dataN1.txt', 'dataN2.txt', ..., 'dataNM.txt']} 

so file1data11 + data12 + ... + data1M etc ist .. .

So sieht mein Code wie folgt aus: wie diese

jobs = [] 
for d in dic: 
    outfile = str(d)+"_merged.txt" 
    with open(outfile, 'w') as out: 
     p = multiprocessing.Process(target = merger.merger, args=(dic[d], name, out)) 
     jobs.append(p) 
     p.start() 
     out.close() 

und die merger.py aussieht:

Ich sehe die Datei auf den Ordner geschrieben gehen soll, aber es ist leer. kein Header, nichts. Ich habe Abzüge hineingelegt, um zu sehen, ob alles in Ordnung ist, aber nichts funktioniert.

Hilfe!

+1

Sie rufen 'out.close()' 'unmittelbar nach p.start()'. Ich bezweifle, dass die Zusammenführungsaufgabe Zeit hat, ausgeführt zu werden, bevor die Datei davon geschlossen wird. – Blorgbeard

+0

@Blorgbeard guter Punkt, aber immer noch nichts ... – Pavlos

+0

Dies ist auf einem Linux wie Betriebssystem, richtig? – tdelaney

Antwort

2

Da die Worker-Prozesse parallel zum Hauptprozess laufen, der sie erstellt, werden die Dateien mit dem Namen out geschlossen, bevor die Worker zu ihnen schreiben können. Dies wird auch dann passieren, wenn Sie out.close() wegen der with Anweisung entfernen. Stattdessen übergeben Sie jedem Prozess den Dateinamen und lassen Sie den Prozess öffnen und schließen Sie die Datei.

+0

@Pavlos nein, behalten Sie die gleiche Anzahl von Prozessen, sondern nur Dateinamen statt Dateiobjekte übergeben. –

+0

Danke! es funktionierte! – Pavlos

+0

Das Schließen der Datei im übergeordneten Element sollte für das untergeordnete Element jedoch kein Problem darstellen. Ich sehe nicht, wie das es repariert hat! – tdelaney

2

Das Problem besteht darin, dass Sie die Datei im Kind nicht schließen, so dass intern gepufferte Daten verloren gehen. Sie können die Datei in das untergeordnete Element verschieben oder das Ganze in einen try/finally-Block einschließen, um sicherzustellen, dass die Datei geschlossen wird. Ein möglicher Vorteil des Öffnens im Parent besteht darin, dass Sie dort Dateifehler behandeln können. Ich sage nicht, es ist überzeugend, nur eine Option.

def merger(files, name, outfile): 
    try: 
     time.sleep(2) 
     sys.stdout.write("Merging %n...\n" % name) 

     # the reason for this step is that all the different files have a header 
     # but I only need the header from the first file. 
     with open(files[0], 'r') as infile: 
      for line in infile: 
       print "writing to outfile: ", name, line 
       outfile.write(line) 
     for f in files[1:]: 
      with open(f, 'r') as infile: 
       next(infile) # skip first line 
       for line in infile: 
        outfile.write(line) 
     sys.stdout.write("Done with: %s\n" % name) 
    finally: 
     outfile.close() 

UPDATE

Es gibt einige Verwirrung über Eltern/Kind-Datei decriptors wurde und was in dem Kind Dateien geschieht. Die zugrunde liegende C-Bibliothek löscht Daten nicht auf die Festplatte, wenn beim Beenden des Programms noch eine Datei geöffnet ist. Die Theorie ist, dass ein richtig laufendes Programm Dinge vor dem Beenden schließt. Hier ist ein Beispiel, in dem das Kind Daten verliert, weil es die Datei nicht schließt.

import multiprocessing as mp 
import os 
import time 

if os.path.exists('mytestfile.txt'): 
    os.remove('mytestfile.txt') 

def worker(f, do_close=False): 
    time.sleep(2) 
    print('writing') 
    f.write("this is data") 
    if do_close: 
     print("closing") 
     f.close() 


print('without close') 
f = open('mytestfile.txt', 'w') 
p = mp.Process(target=worker, args=(f, False)) 
p.start() 
f.close() 
p.join() 
print('file data:', open('mytestfile.txt').read()) 

print('with close') 
os.remove('mytestfile.txt') 
f = open('mytestfile.txt', 'w') 
p = mp.Process(target=worker, args=(f, True)) 
p.start() 
f.close() 
p.join() 
print('file data:', open('mytestfile.txt').read()) 

ich es auf Linux laufen und ich

without close 
writing 
file data: 
with close 
writing 
closing 
file data: this is data 
+0

Hier ist, was ich unter Windows (Python 2 und 3): http://pastebin.com/kwTAaT5t - Tldr: Fehler. – Blorgbeard

+0

Nicht unerwartet. Windows versucht, die Datei erneut zu öffnen, es ist jedoch nicht für die Freigabe geöffnet. Nicht falsch. Einfach anders. – tdelaney

Verwandte Themen