getattr() und setattr() NetCDF

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
styriker
User
Beiträge: 3
Registriert: Freitag 22. Juli 2011, 10:19

Hi Leute,
der newbie von nebenan nochmal. Mein früheres Problem hat sich gelöst.Ich arbeite jetzt mit Scientific.IO.NetCDF.
Ich versuche gerade eine NetCDF-Datei zu kopieren, weil ich eben dimensionen, variablen und attribute teilweise übernehme und später teilweise ändere.
Dazu will ich jetzt auch die Attribute kopieren. Dieses wollte ich mit get und set machen. Sicher nicht so praktisch, wie ihr bestimmt wisst und wie mir der Segmentation Fault gezeigt hat. Deshalb unten der Code.


Der Segmentation Fault kam vor der zweitletzten Zeile.
Das letzte "VarAttValue" sollte den Fehler auslösen. Wie kann ich das Attribut von einer netcdf automatisch zu einer neuen Datei hinzufügen?


Das problem ist wohl, dass einige attribute built-in Methoden sind und andere attribute sind eben wowas wie 'units', also sehr nützlich.
>>> VarAttNames
['assignValue', 'getValue', 'long_name', 'typecode', 'units']
>>> VarAttValue=getattr(VarName,VarAttNames[1],None)
>>> VarAttValue
<built-in method getValue of NetCDFVariable object at 0xc37c00>
>>> VarAttValue=getattr(VarName,VarAttNames[2])
>>> print VarAttValue
longitude of west edge
Der Code (excl. sample file):

Code: Alles auswählen

from Scientific.N import *
from Scientific.IO.NetCDF import *
import time
import os, pwd, string
import sys
from sys import argv
import readline

#Open griddata file (5 x 5 cells)
filemk = NetCDFFile('griddata_0005x0005.nc', 'r')
#print filemk.dimensions
#print filemk.variables

filenew = NetCDFFile('newgriddata.nc','w','Created'+time.ctime(time.time())+'by r.baatz')

#read and add dimensions
dims = filemk.dimensions.keys()
dimval = zeros(len(dims),Int)
for ii in range(len(dims)):
         dimval[ii] = filemk.dimensions[dims[ii]]

for ii in range(len(dims)):
        filenew.createDimension(dims[ii],int(dimval[ii]))
        # mission #1 accomplished

mkVariables = filemk.variables.keys()
for ii in range(len(mkVariables)):
        print ii
        #Step1 GET
        VarName = filemk.variables[mkVariables[ii]]     #get name of variable
        VarType = VarName.typecode()                    #get type
        VarShape = VarName.shape                                #get shape
        VarDims = VarName.dimensions                    #get dimensions
        VarData = VarName.getValue()                    #get values (data = zeros(VarName.shape))
        #Step2 SET
        VarNetCDF = filenew.createVariable(mkVariables[ii],VarType,VarDims)
        VarAttNames = dir(VarName)                                      #get variable attributes
        for jj in range(len(VarAttNames)):                      #set variable attributes 1 to n
                print jj
                VarAttValue=getattr(VarName,VarAttNames[jj])
                print jj
                setattr(VarNetCDF, VarAttNames[jj], VarAttValue)
                               
        VarNetCDF.assignValue(VarData)

Besten Dank schonmal, falls ich vergessen sollte zu antworten :)
Werd mir aber Mühe geben!
BlackJack

@styriker: Das mit dem Absturz ist ein wenig unschön, aber so kann das auch nicht funktionieren. Attribute eines Objekts sind in Python nicht nur „Daten” sondern *alles* was mit einem Namen an ein Objekt gebunden ist. Also zum Beispiel auch Methoden. Die kann man auch als Daten behandeln und an andere Namen binden, oder als Argumente bei Aufrufen übergeben und so weiter. Es macht wenig Sinn gebundene Methoden als Attribute eines anderen Objektes zu binden, denn die haben weiterhin das Ursprungsobjekt als erstes Argument gebunden. Im Gegensatz zum Beispiel zu JavaScript. Eine unabhängige Kopie kann man so auch nicht bekommen, weil in Python in aller Regel keine Objekte kopiert werden, wenn man das nicht explizit sagt. Nach `b.x = a.x` referenzieren beide Attribute das *selbe* Objekt.

Sind die Attribute denn für die Variablen verschieden? Wenn sie immer gleich sind, könntest Du es ja einfach ausschreiben.

Sonstige Anmerkung zum Code: Das sieht nicht besonders „pythonisch” aus. ``for index in xrange(len(obj))`` ist in 99% der Fälle unnötig indirekt. Man kann in der Schleife auch *direkt* über die Elemente iterieren, ohne den Umweg über einen Index. Bei Wörterbüchern kann man auch in einer Schleife direkt über die Schlüssel/Wert-Paare iterieren.

Das mit den Dimensionen sieht auch umständlich aus. Zum einen ist es in Python unüblich ein Array oder eine Liste mit einer bestimmten Länge zu erstellen und dann sequenziell die Werte zu setzen, zum anderen sehe ich den Sinn von `dims` und `dimval` nicht ganz, denn das müsste man doch auch in *einer* Schleife ohne die Listen/Arrays machen können:

Code: Alles auswählen

for dimension, value in filemk.dimensions.iteritems():
    filenew.createDimension(dimension, int(value))
    # mission #1 accomplished
styriker
User
Beiträge: 3
Registriert: Freitag 22. Juli 2011, 10:19

Hi jack,

also ich habe jetzt das indirekte in direkt umgewandelt und bin auch um die Listen und Arrays herumgekommen. Sieht natürlich verständlicher aus.

Die Attribute der Variablen wären verschieden, ja. Ich wollte eben um das ausschreiben drum herum kommen und so viel wie möglich automatisch machen.
Sollte das nicht gehen, muss ich die Attribute per Hand setzen.
Antworten