Package Gnumed :: Package pycommon :: Module gmdbf |
[frames] | no frames]

# Source Code for Module Gnumed.pycommon.gmdbf

      1  #
      2  # dbf.py version 0.2
      3  # 1999/11/12
      4  #
      5  # A module for reading dbf files. Tested ONLY on Linux.
      6  #
      7  # Author        : Michal Spalinski (mspal@curie.harvard.edu)
      8  #                 minor changes (dictresult) by H.Herb
      9  # Copying policy: unlimited (do what you want with it)
     10  # Warranty      : none whatsoever
     11  #
     12  # URL: http://schwinger.harvard.edu/~mspal/pystuff.html
     13
     14
     15  """
     16  This is a module for reading dbf files.
     17
     18  It has been modified thanks to suggestions and patches from Jeff Bauer
     19  and Kevin Dahlhausen. Unfortunately I lost patches which fix
     20  endianness problems, which were sent to me by someone, so that will
     21  have to wait. I do not use this module much these days, but since it
     22  seems to be in use "out there" I thought I would finally make an
     23  update available. This version should be more portable. Also, rather
     24  than printing an error message an exception is now raised when the dbf
     25  file appears to be corrupt.
     26
     27  Usage: the following
     28
     29  import dbf
     30  db = dbf.dbf('mydata.dbf')
     31
     32  creates a dbf object db associated with an existing dbf file
     33  'mydata.dbf'.  The dbf file is opened by the constructor. If the file
     34  is not there IOError is raised. If the file appears not to be a dbf
     35  format file, TypeError is raised.
     36
     37  If you prefer to create a dbf object, but open the actual file later,
     38  you can use the following:
     39
     40  import dbf
     41  db = dbf.dbf('mydata.dbf', openit=0)
     42
     43  and then you can call
     44
     45  db.open()
     46
     47  to actually open the file. Note that the constructor, if called this
     48  way, does not verify that the file is there, so the IOError exception
     49  is raised by the call to open.
     50
     51  Once the dbf object is created and opened (implicitly or not), the
     52  following are available:
     53
     54  -- db.fields  : returns a a list of tuples describing the fields
     55  -- db.nrecs   : returns the number of records
     56  -- db[n]      : returns a tuple containing record number n (0 <= n < nrecs)
     57  -- db.status(): prints some essential data about the dbf file
     58
     59  So to list the first two fields of mydata.dbf, assuming they are string
     60  fields, one might write:
     61
     62  import dbf
     63  from string import strip
     64  db=dbf.dbf('mydata.dbf')
     65  for k in db:
     66      print "%s, %s" % (strip(k[1]), strip(k[2]))
     67
     68
     69  Good luck!
     70
     71  """
     72
     73
     74  from struct import unpack
     75
     76 -class dbf:
     77 -        def __init__(self, fname, openit=1):
     78                  self.fname = fname
     79                  if openit:
     80                          self.open()
     81
     82 -        def open(self):
     83                  self.f = open(self.fname,'rb')
     84                  head = self.f.read(32)
     85                  if (head[0] != '\003') and (head[0] != '\203') and (head[0] != '\365'):
     86                          raise TypeError, 'Not a Dbase III+ file!'
     87                  (self.nrecs, self.hlen, self.rlen) = unpack('4xihh20x', head)
     88                  fdalen = (self.hlen - 33)/32
     89                  # read field descriptor array
     90                  fda = []
     91                  for k in range(fdalen):
     92                          fda.append(self.f.read(32))
     93                  # interpret the field descriptors
     94                  self.fields = []
     95                  #field index dictionary
     96                  self.fieldindex = {}
     97                  idx = 0
     98                  for fd in fda:
     99                          bytes = unpack('12c4xBb14x', fd)
    100                          field = ""
    101                          for i in range(11):
    102                                  if bytes[i] == '\000':
    103                                          break
    104                                  field = field+bytes[i]
    105                          type = bytes[11]
    106                          length = bytes[12]
    107                          dec = bytes[13]
    108                          self.fields.append((field,type,length,dec))
    109                          self.fieldindex[idx]=field
    110                          idx=idx+1
    111
    112          # record numbers go from 0 to self.nrecs-1
    113 -        def _get(self, recno):
    114                  offs = self.hlen + recno*self.rlen
    115                  self.f.seek(offs,0)
    116                  return self.f.read(self.rlen)
    117
    118 -        def __getitem__(self, recno):
    119                  if recno < 0 or recno >= self.nrecs:
    120                          raise IndexError
    121                  else:
    122                          raw = self._get(recno)
    123                  res = []
    124                  pos = 0
    125                  for field in self.fields:
    126                          end = pos+field[2]
    127                          item = raw[pos+1:end+1]
    128                          pos=end
    129                          res.append(item)
    130                  return tuple(res)
    131
    132 -        def dictresult(self, recno):
    133                  res = self.__getitem__(recno)
    134                  d = {}
    135                  i = 0
    136                  for field in res:
    137                          d[self.fieldindex[i]]=field
    138                          i = i+1
    139                  return d
    140
    141
    142
    143
    144 -        def status(self):
    145                  print ''
    146                  print 'Header length     :', self.hlen
    147                  print 'Record length     :', self.rlen
    148                  print 'Number of records :',  self.nrecs
    149                  print ''
    150                  print '%-12s %-12s %-12s %-12s' % ('Field','Type','Length','Decimal')
    151                  print '%-12s %-12s %-12s %-12s' % ('-----','----','------','-------')
    152                  for k in self.fields:
    153                          print '%-12s %-12s %-12s %-12s' % k
    154                  print ''
    155
    156 -        def close(self):
    157                  self.f.close()
    158
    159
    160  #=====================================================================
    161  # $Log: gmdbf.py,v $
    162  # Revision 1.1  2004-02-25 09:30:13  ncq
    163  # - moved here from python-common
    164  #
    165