Building Very Large Records
Dave Brueck
dave at pythonapocrypha.com
Fri Sep 10 14:52:08 EDT 2004
Greg Lindstrom wrote:
> Hello-
>
> I am working on a routine to pull information from an Oracle database and
> format it into fixed-length records. My problem is that the record layout
> is quite long (over 500 bytes) and contains dozens of fields. How would
> *you* go about building such a beast? I know that using the += operator is
> a bad idea, as it creates a new copy of the string each time. How about the
> struct.pack() method? A very big '%-12.12s%-50.50s.......' statement?
> Other ideas? It does not have to be blazingly fast, but it doesn't have to
> suck, either. I don't know enough about Oracle SQL yet, could I format the
> data in the SQL call?
Here's what I do, maybe somebody can suggest some improvements upon it:
Derive your record from ctypes' Structure class:
class XHeader(Structure):
_pack_ = 1 # No alignment padding
_fields_ = [('ucid', c_ulonglong),
('majorVer', c_ubyte),
('minorVer', c_ubyte),
('extent', c_ulonglong),
('future', c_byte),
('titleLen', c_ubyte)]
Then to serialize it to a string:
def ObjAsString(obj):
'Takes a ctypes object (works on structures too) and returns it as a string'
# There is probably a better way, but this seems to work ok
sz = sizeof(obj)
RawType = c_char * sz
ptr = RawType.from_address(addressof(obj))
return ptr.raw[:sz]
To go the other direction:
def StringAsObject(s, ObjType):
'Takes a string and returns it as a ctypes object'
z = c_buffer(s)
x = ObjType.from_address(addressof(z))
x.__internal = z #ugly hack - save a ref to the c_buffer!
return x
Basic usage is:
x = XHeader()
x.majorVer = 5
...etc...
StuffIntoDB(ObjAsString(x))
newX = StringAsObject(ReadFromDB(), XHeader)
I haven't used it with tons of object instances, so you may need to see if you
end up with memory leaks.
-Dave
More information about the Python-list
mailing list