Wie kann ich temporäre Dateien aus Python Pyramid bereitstellen?

8

Momentan diene ich nur Dateien wie folgt:

%Vor%

Das Problem dabei ist, dass ich die Datei nicht schließen oder besser noch löschen kann, nachdem die Antwort zurückgegeben wurde. Die Datei wird verwaist. Ich kann mir ein paar hacky Wege vorstellen, aber ich hoffe, dass es irgendwo einen Standard gibt. Jede Hilfe wäre großartig.

    
MFB 18.10.2012, 07:14
quelle

6 Antworten

9

Sie möchten keinen Dateizeiger als app_iter festlegen. Dies führt dazu, dass der WSGI-Server die Datei zeilenweise liest (wie for line in file ), was normalerweise nicht der effizienteste Weg ist, um einen Datei-Upload zu steuern (stellen Sie sich ein Zeichen pro Zeile vor). Pyramid unterstützt Dateien, die Dateien bereitstellen, über pyramid.response.FileResponse . Sie können eine davon erstellen, indem Sie ein Dateiobjekt übergeben.

%Vor%

Eine andere Option besteht darin, einen Dateizeiger an app_iter zu übergeben, ihn jedoch in das Objekt pyramid.response.FileIter zu wickeln, das eine vernünftige Blockgröße verwendet, um das zeilenweise Lesen der Datei zu vermeiden.

Die WSGI-Spezifikation hat strenge Anforderungen, dass Antwort-Iteratoren, die eine close -Methode enthalten, am Ende der Antwort aufgerufen werden. Daher sollte response.app_iter = open(...) keine Speicherlecks verursachen. Sowohl FileResponse als auch FileIter unterstützen auch eine close -Methode und werden daher wie erwartet bereinigt.

Als kleines Update zu dieser Antwort dachte ich, ich würde erklären, warum FileResponse einen Dateipfad und keinen Dateizeiger benötigt. Das WSGI-Protokoll bietet Servern optional die Möglichkeit, einen optimierten Mechanismus für die Bereitstellung statischer Dateien über environ['wsgi.file_wrapper'] bereitzustellen. FileResponse wird dies automatisch behandeln, wenn Ihr WSGI-Server diese Unterstützung bereitgestellt hat. In diesem Sinne ist es ein Gewinn, Ihre Daten in einer tmpfile auf einer Ramdisk zu speichern und FileResponse mit dem vollständigen Pfad anzugeben, anstatt zu versuchen, einen Dateizeiger an FileIter zu übergeben.

Ссылка

    
Michael Merickel 18.10.2012, 15:56
quelle
8

Aktualisierung:

Siehe Michael Merickels Antwort für eine bessere Lösung und Erklärung.

Wenn Sie die Datei löschen möchten, nachdem response zurückgegeben wurde, können Sie Folgendes versuchen:

%Vor%

Sie können NamedTemporaryFile in Erwägung ziehen:

%Vor%

Einstellung von delete=True , so dass die Datei gelöscht wird, sobald sie geschlossen wird.

Nun können Sie mit Hilfe von with immer die Sicherheit haben, dass die Datei geschlossen und damit gelöscht wird:

%Vor%     
K Z 18.10.2012 08:50
quelle
2

Die Kombination von Michael und Kay's Antwort funktioniert gut unter Linux / Mac, funktioniert aber nicht unter Windows (zum automatischen Löschen). Windows mag es nicht, dass FileResponse versucht, die bereits geöffnete Datei zu öffnen (siehe Beschreibung von NamedTemporaryFile).

Ich habe daran gearbeitet, indem ich eine FileDecriptorResponse-Klasse erstellt habe, die im Wesentlichen eine Kopie von FileResponse ist, aber den Dateideskriptor der geöffneten NamedTemporaryFile übernimmt. Ersetzen Sie einfach das Öffnen durch eine Suche (0) und alle pfadbasierten Aufrufe (last_modified, content_length) durch ihre fstat-Entsprechungen.

%Vor%

Ich hoffe, das ist hilfreich.

    
Justin 04.12.2012 01:46
quelle
1

Es gibt auch repoze.filesafe , das dafür sorgt, dass eine temporäre Datei für Sie erstellt und am Ende gelöscht wird . Ich verwende es zum Speichern von Dateien auf meinem Server hochgeladen. Vielleicht kann es auch für Sie nützlich sein.

    
Raj 18.10.2012 14:35
quelle
0

Weil Ihre Objekt Antwort eine Dateikennung für die Datei '/temp/XML_Export_%s.xml' enthält. Verwenden Sie die Anweisung del , um das Handle 'response.app_iter' zu löschen.

%Vor%     
abhilash 18.10.2012 09:02
quelle
0

Sowohl Michael Merickel als auch Kay Zhu sind in Ordnung. Ich habe herausgefunden, dass ich auch die Dateiposition im Begninnign der NamedTemporaryFile zurücksetzen muss, bevor ich sie an die Response übergebe, da es so aussieht, als ob die Antwort von der tatsächlichen Position in der Datei und nicht von Anfang an beginnt (Es reicht jetzt es). Mit NamedTemporaryFile mit Deletion-Set können Sie es nicht schließen und erneut öffnen, da es es löschen würde (und Sie können es trotzdem nicht erneut öffnen), also müssen Sie etwas wie folgt verwenden:

%Vor%

hoffe es hilft;)

    
pdepmcp 27.11.2014 15:52
quelle

Tags und Links