2013-12-13 4 views
8

Ich habe eine fragmentierte Struktur im Speicher, und ich möchte es als eine zusammenhängend aussehende Gedächtnisansicht zugreifen. Gibt es einen einfachen Weg dies zu tun oder sollte ich meine eigene Lösung implementieren?Wie erstellt man eine Speicheransicht für einen nicht zusammenhängenden Speicherort?

Betrachten Sie beispielsweise ein Dateiformat, das aus Datensätzen besteht. Jeder Datensatz hat einen Header fester Länge, der die Länge des Inhalts des Datensatzes angibt. Eine logische Struktur höherer Ebene kann sich über mehrere Datensätze erstrecken. Es würde das Implementieren der Struktur auf höherer Ebene einfacher machen, wenn es seinen eigenen fragmentierten Speicherort als ein einfaches zusammenhängendes Array von Bytes sehen könnte.

Update:

Es scheint, dass Python unterstützt diese 'segmentiert' Puffer intern geben, zumindest bezogen auf this part of the documentation. Aber das ist nur die C-API.

Update2:

Soweit ich sehe, die referenzierte C API - im alten Stil Puffer genannt - das tut, was ich brauche, aber es ist jetzt veraltet und nicht verfügbar in neuerer Version von Python (3.X) . Das neue Pufferprotokoll - spezifiziert in PEP 3118 - bietet eine neue Möglichkeit, Puffer darzustellen. Diese API ist in den meisten Anwendungsfällen (z. B. Anwendungsfälle, in denen der dargestellte Puffer nicht zusammenhängend ist) besser benutzbar, unterstützt jedoch nicht diese spezielle, bei der ein eindimensionales Array vollständig frei ausgelegt werden kann (mehrfach anders) Größe Chunks) im Speicher.

+1

Erstens ist eine Datei selten eine Speicherstruktur. Zweitens, warum und auf welche Weise müssen Sie auf Low-Level-Speicherstrukturen zugreifen und es sogar mit Python machen? Die Frage scheint zum Beispiel für C oder C++ oder andere Sprachen mit Dev-gesteuerter Speicherzuordnung und -zugriff besser geeignet zu sein. – alko

+1

Eine verknüpfte Liste durchlaufen und jede Daten drucken? – perreal

+1

Eine Datei wird zu einer Speicherstruktur, wenn Sie sie mit mmap (auch in Python verfügbar) verknüpfen. Ja, es ist möglich, eine verkettete Liste zu durchlaufen, aber der Punkt ist, dass ich mit einer einfachen Schnittstelle wie der Schnittstelle von memoryview darauf zugreifen möchte. Ich denke, es ist möglich, da die Dokumentation erwähnt, dass Sie es verwenden können, um nicht zusammenhängende Daten (z. B. NumPy-Arrays) zuzugreifen. – molnarg

Antwort

1

Erstens - ich nehme an, dass Sie nur versuchen, dies in reinem Python und nicht in einer c-Erweiterung zu tun. Ich gehe also davon aus, dass Sie die verschiedenen Datensätze, die Sie interessieren, in eine Reihe von Python-Objekten geladen haben. Ihr Problem ist, dass Sie die Struktur auf höherer Ebene sehen wollen, die über diese Objekte verteilt ist.

Also können Sie nicht einfach jeden der Datensätze in einen Byte-Array-Typ laden? Sie können dann das Python-Slicing von Arrays verwenden, um ein neues Array zu erstellen, das nur die Daten für die Struktur auf hoher Ebene enthält. Sie haben dann ein einzelnes Byte-Array mit nur den Daten, an denen Sie interessiert sind, und können es ausdrucken manipuliere es so, wie du es willst.

So etwas wie:

a = bytearray(b"Hello World") # put your records into byte arrays like this 
b = bytearray(b"Stack Overflow") 
complexStructure = bytearray(a[0:6]+b[0:]) # Slice and join arrays to form 
              # new array with just data from your 
              # high level entity 
print complexStructure 

Natürlich wird noch ned Sie wissen, wo innerhalb der Datensätze Ihre hohe Level-Struktur, die Arrays richtig zu schneiden, aber Sie würden es sowieso wissen müssen.

EDIT:

Hinweis ein Stück einer Liste nehmen die Daten nicht in der Liste kopiert es erzeugt nur einen neuen Satz von Verweisen auf die Daten so:

>>> a = [1,2,3] 
>>> b = a[1:3] 
>>> id(a[1]) 
140268972083088 
>>> id(b[0]) 
140268972083088 

jedoch Änderungen Die Liste b wird nicht geändert, da b eine neue Liste ist. Damit die Änderungen automatisch in der ursprünglichen Liste geändert werden, müssen Sie ein komplizierteres Objekt erstellen, das die Listen in den ursprünglichen Datensätzen enthält, und sie so verbergen, dass Sie entscheiden können, welche Liste und welches Element einer Liste geändert werden soll oder anzeigen, wenn ein Benutzer die komplexe Struktur ändern/anzeigen möchte. Also etwas wie:

class ComplexStructure(): 
    def add_records(self,record): 
     self.listofrecords.append(record) 

    def get_value(self,position): 
     listnum,posinlist = ... # formula to figure out which list and where in 
           # list element of complex structure is 
     return self.listofrecords[listnum][record] 

    def set_value(self,position,value): 
     listnum,posinlist = ... # formula to figure out which list and where in 
           # list element of complex structure is 
     self.listofrecords[listnum][record] = value 

Zugegeben, das ist nicht die einfache Art, Dinge zu tun, auf die Sie gehofft haben, aber es sollte tun, was Sie brauchen.

+0

Es ist eine gute Lösung für bestimmte Anwendungsfälle, ja. Die Hauptunterschiede von memoryview sind: 1. Dies erfordert das Kopieren von Daten um 2. Wenn die neue Datenstruktur modifiziert wird, hat dies keine Auswirkungen auf den ursprünglichen Puffer, die Änderungen müssen zurückkopiert werden. In einer idealen Lösung würde ich gerne diese beiden Eigenschaften sehen. – molnarg

+0

molnarg: Es wurde eine Bearbeitung hinzugefügt, um Ihre zusätzlichen zwei Eigenschaften zu behandeln. – Tommy

+0

Danke, es scheint die einzige Lösung zu sein, da es mit den integrierten APIs wahrscheinlich nicht machbar ist. – molnarg