Wie verarbeite ich virtuelle Dateien?

70

Zum Erstellen von Dateien verwende ich Folgendes:

fileHandle = open('fileName', 'w')

Schreiben Sie dann den Inhalt in die Datei und schließen Sie die Datei. Im nächsten Schritt verarbeite ich die Datei. Am Ende des Programms erhalte ich eine "physische Datei", die ich löschen muss.

Gibt es eine Möglichkeit, eine "virtuelle" Datei zu schreiben, die sich genau wie eine "physische" verhält (so dass sie auf die gleiche Weise bearbeitet werden kann), aber am Ende des Laufs in Python nicht vorhanden ist?

Steve Grafton
quelle

Antworten:

70

Möglicherweise möchten Sie eine verwenden, tempfile.SpooledTemporaryFiledie Ihnen das Beste aus beiden Welten bietet, da zunächst eine temporäre speicherbasierte virtuelle Datei erstellt wird, automatisch jedoch zu einer physischen festplattenbasierten Datei gewechselt wird, wenn die im Speicher gespeicherten Daten einen bestimmten Wert überschreiten Größe.

Eine weitere nette Funktion ist, dass (bei Verwendung des Speichers) automatisch entweder ein io.BytesIOoder io.StringIOje nach verwendetem Speicher modeverwendet wird, sodass Sie entweder Unicode-Zeichenfolgen oder Binärdaten (Bytes) lesen und schreiben können.

Der einzige schwierige Teil könnte die Tatsache sein, dass Sie das Schließen der Datei zwischen den Schritten vermeiden müssen, da dies dazu führen würde, dass sie aus dem Speicher oder der Festplatte gelöscht wird. Stattdessen können Sie es einfach mit einem Dateimethodenaufruf zum Anfang zurückspulen seek(0).

Wenn Sie mit der Datei fertig sind und sie schließen, wird sie automatisch von der Festplatte gelöscht, wenn die darin enthaltene Datenmenge dazu führte, dass sie auf eine physische Datei übertragen wurde.

Martineau
quelle
Relevante Beispiele: stackoverflow.com/questions/8577137/…
Anton Tarasenko
2
Wenn Sie von einer anderen Frage hierher kommen, ist es erwähnenswert, dass es keinen Dateinamen für diese temporäre In-Memory-Datei gibt (man muss den Handler bearbeiten). Die Lösung eignet sich jedoch hervorragend für die OP-Nutzung (+1). Was leider im Modul fehlt, ist tempfile.NamedSpooledTemporaryFile()(eine Kombination aus NamedTemporaryFile()und SpooledTemporaryFile())
WoJ
@WoJ: Danke für die +1. Ich denke, der Grund dafür tempfile.NamedSpooledTemporaryFile()ist, dass es keinen Sinn macht zu sagen, dass etwas, das als speicherbasierte virtuelle Datei beginnt, garantiert einen sichtbaren Namen im Dateisystem hat - obwohl es irgendwann einen haben könnte , sollte es sein Größe überschreitet den angegebenen max_sizeSchwellenwert. Der Quellcode für das tempfileModul befindet sich in python/Lib/tempfile.py. Dies kann hilfreich sein, wenn Sie selbst etwas mit dem gewünschten Verhalten implementieren möchten (was auch immer der Fall sein mag, wenn sich die Daten gerade im Speicher befinden).
Martineau
53

Sie haben StringIOund BytesIOim ioModul.

StringIOverhält sich wie eine im Textmodus geöffnete Datei - Lesen und Schreiben von Unicode-Zeichenfolgen (entspricht dem Öffnen einer Datei mit io.open(filename, mode, encoding='...')), und BytesIOverhält sich wie eine im Binärmodus geöffnete Datei ( mode='[rw]b') und kann Schreibbytes lesen.

Python 2:

In [4]: f = io.BytesIO('test')
In [5]: type(f.read())
Out[5]: str
In [6]: f = io.StringIO(u'test')
In [7]: type(f.read())
Out[7]: unicode

Python 3:

In [2]: f = io.BytesIO(b'test')
In [3]: type(f.read())
Out[3]: builtins.bytes
In [4]: f = io.StringIO('test')
In [5]: type(f.read())
Out[5]: builtins.str
Viktor Kerkez
quelle
11
Es sollte beachtet werden, dass, falls Sie eine Schnittstelle mit Code benötigen, der Dateinamen benötigt, Folgendes gilt: Wenn Ihr Legacy-Code nur einen Dateinamen annehmen kann, ist eine StringIOInstanz nicht der richtige Weg. Verwenden Sie das tempfileModul, um stattdessen einen temporären Dateinamen zu generieren.
Sdaau
13

Sie können StringIO als virtuelle Datei aus der offiziellen Dokumentation verwenden

from io import StringIO

output = StringIO()
output.write('First line.\n')
print >>output, 'Second line.'

# Retrieve file contents -- this will be
# 'First line.\nSecond line.\n'
contents = output.getvalue()

# Close object and discard memory buffer --
# .getvalue() will now raise an exception.
output.close()
Srinivas Reddy Thatiparthy
quelle
10
Denken Sie daran, wenn Sie es als dateiähnliches Objekt an eine andere Funktion übergeben möchten, sollten Sie die virtuelle Datei zurückspulen mit: output.seek (0)
RufusVS
1
Mann, kopierst du aus der offiziellen Dokumentation? :) Ich denke, es ist fair, in solchen Fällen einen Link zu verwenden.
Maxadamo
@ Maxadamo Fertig. Vielen Dank.
Srinivas Reddy Thatiparthy
2
from io import StringIOfür Python> = 3
Christof
0

Da ist das StringIOModul, lesen Sie seine Dokumentation , es sollte einfach zu bedienen sein.

Beachten Sie jedoch, dass dadurch der Inhalt der "Datei" im Speicher bleibt. Wenn Sie zu viele Daten haben, ist es wahrscheinlich besser, eine echte Datei zu erstellen, z. B. in / tmp, und diese anschließend zu löschen.

Nickie
quelle
0

Wenn Sie anstelle einer Datei in den Speicher schreiben möchten, können Sie den Text einfach in einen Puffer schreiben und die folgende Funktion verwenden:

def write(text):
  global buffer
  buffer += text + '\n'  # Add a linefeed as you would if you were writing to a file

buffer = ""  # Initialize the buffer
write("My name is Steve Grafton")

Am Ende haben Sie einen Puffer, der dem entspricht, als hätten Sie Ihre Daten in eine Datei geschrieben. Öffnen Sie dann die Datei und lesen Sie den gesamten Inhalt in einen Puffer! Darüber hinaus können Sie den Puffer während des Vorgangs (bevor Sie mit dem Schreiben fertig sind) verwenden und darin suchen, als hätten Sie eine Datei zum Lesen und Schreiben erstellt, nur in diesem Fall Ihren Zeiger

Apostolos
quelle