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