title: <type 'exceptions.IOError'> [Errno 9] Bad file descriptor
body: <p>The code below is a part of a program which is aimed to capture data from Bloomberg terminal and dump it into SQLite database. It worked pretty well on my 32-bit windows XP. But it keeps giving me 
  "get_history.histfetch error:  [Errno 9] Bad file descriptor" on 64-bit windows 7, although there shouldn't be a problem using 32-bit python under 64-bit OS. Sometimes this problem can be solved by simply exit the program and open it again, but sometimes it just won't work. Right now I'm really confused about what leads to this problem. I looked at the source code and found the problem is generated while calling "histfetch" and I have NO idea which part of the code is failing. Can anyone help me out here...? I really really appreciate it. Thanks in advance.</p>
  
  <pre><code>def run(self):
      try: pythoncom.CoInitializeEx(pythoncom.COINIT_APARTMENTTHREADED)
      except: pass
      while 1:
          if self.trigger:
              try: self.histfetch()
              except Exception,e:
                  logging.error('get_history.histfetch error: %s %s' % (str(type(e)),str(e)))
                  if self.errornotify != None:
                      self.errornotify('get_history error','%s %s' % ( str(type(e)), str(e) ) )
              self.trigger = 0
          if self.telomere: break
          time.sleep(0.5)
  
  def histfetch(self):
      blpcon = win32com.client.gencache.EnsureDispatch('blpapicom.Session')
      blpcon.Start()
      dbcon = sqlite3.connect(self.dbfile)
      c = dbcon.cursor()
      fieldcodes = {}
      symcodes = {}
      trysleep(c,'select fid,field from fields')
      for fid,field in c.fetchall():
          # these are different types so this will be ok
          fieldcodes[fid] = field
          fieldcodes[field] = fid
      trysleep(c,'select sid,symbol from symbols')
      for sid,symbol in c.fetchall():
          symcodes[sid] = symbol
          symcodes[symbol] = sid
      for instr in self.instructions:
          if instr[1] != 'minute': continue
          sym,rollspec = instr[0],instr[2]
          print 'MINUTE',sym
          limits = []
          sid = getsid(sym,symcodes,dbcon,c)
          trysleep(c,'select min(epoch),max(epoch) from minute where sid=?',(sid,))
          try: mine,maxe = c.fetchone()
          except: mine,maxe = None,None
          print sym,'minute data limits',mine,maxe
          rr = getreqrange(mine,maxe)
          if rr == None: continue
          start,end = rr
          dstart = start.strftime('%Y%m%d')
          dend = end.strftime('%Y%m%d')
          try: # if rollspec is 'noroll', then this will fail and goto except-block
              ndaysbefore = int(rollspec)
              print 'hist fetch for %s, %i days' % (sym,ndaysbefore)
              rolldb.update_roll_db(blpcon,(sym,))
              names = rolldb.get_contract_range(sym,ndaysbefore)
          except: names = {sym:None}
          # sort alphabetically here so oldest always gets done first
          #  (at least within the decade)
          sorted_contracts = names.keys()
          sorted_contracts.sort()
          for contract in sorted_contracts:
              print 'partial fetch',contract,names[contract]
              if names[contract] == None:
                  _start,_end = start,end
              else:
                  da,db = names[contract]
                  dc,dd = start,end
                  try: _start,_end = get_overlap(da,db,dc,dd)
                  except: continue # because get_overlap returning None cannot assign to tuple
              # localstart and end are for printing and logging
              localstart = _start.strftime('%Y/%m/%d %H:%M')
              localend = _end.strftime('%Y/%m/%d %H:%M')
              _start = datetime.utcfromtimestamp(time.mktime(_start.timetuple())).strftime(self.blpfmt)
              _end = datetime.utcfromtimestamp(time.mktime(_end.timetuple())).strftime(self.blpfmt)
              logging.debug('requesting intraday bars for %s (%s): %s to %s' % (sym,contract,localstart,localend))
              print 'start,end:',localstart,localend
              result = get_minute(blpcon,contract,_start,_end)
              if len(result) == 0:
                  logging.error('warning: 0-length minute data fetch for %s,%s,%s' % (contract,_start,_end))
                  continue
              event_count = len(result.values()[0])
              print event_count,'events returned'
              lap = time.clock()
              # todo: split up writes: no more than 5000 before commit (so other threads get a chance)
              #   100,000 rows is 13 seconds on my machine. 5000 should be 0.5 seconds.
              try:
                  for i in range(event_count):
                      epoch = calendar.timegm(datetime.strptime(str(result['time'][i]),'%m/%d/%y %H:%M:%S').timetuple())
                      # this uses sid (from sym), NOT contract
                      row = (sid,epoch,result['open'][i],result['high'][i],result['low'][i],result['close'][i],result['volume'][i],result['numEvents'][i])
                      trysleep(c,'insert or ignore into minute (sid,epoch,open,high,low,close,volume,nevents) values (?,?,?,?,?,?,?,?)',row)
                  dbcon.commit()
              except Exception,e:
                  print 'ERROR',e,'iterating result object'
                  logging.error(datetime.now().strftime() + ' error in get_history.histfetch writing DB')
                  # todo: tray notify the error and log it
              lap = time.clock() - lap
              print 'database write of %i rows in %.2f seconds' % (event_count,lap)
              logging.debug(' -- minute bars %i rows (%.2f s)' % (event_count,lap))
      for instr in self.instructions:
          oldestdaily = datetime.now().replace(hour=0,minute=0,second=0,microsecond=0) - timedelta(self.dailyback)
          sym = instr[0]
          if instr[1] != 'daily': continue
          print 'DAILY',sym
          fields = instr[2]
          rollspec = instr[3]
          sid = getsid(sym,symcodes,dbcon,c)
          unionrange = None,None
          for f in fields:
              try: fid = fieldcodes[f]
              except:
                  trysleep(c,'insert into fields (field) values (?)',(f,))
                  trysleep(c,'select fid from fields where field=?',(f,))
                  fid, = c.fetchone()
                  dbcon.commit()
                  fieldcodes[fid] = f
                  fieldcodes[f] = fid
              trysleep(c,'select min(epoch),max(epoch) from daily where sid=? and fid=?',(sid,fid))
              mine,maxe = c.fetchone()
              if mine == None or maxe == None:
                  unionrange = None
                  break
              if unionrange == (None,None):
                  unionrange = mine,maxe
              else:
                  unionrange = max(mine,unionrange[0]),min(maxe,unionrange[1])
          print sym,'daily unionrange',unionrange
          yesterday = datetime.now().replace(hour=0,minute=0,second=0,microsecond=0) - timedelta(days=1)
          if unionrange == None:
              reqrange = oldestdaily,yesterday
          else:
              mine = datetime.fromordinal(unionrange[0])
              maxe = datetime.fromordinal(unionrange[1])
              print 'comparing',mine,maxe,oldestdaily,yesterday
              if oldestdaily &lt; datetime.fromordinal(unionrange[0]): a = oldestdaily
              else: a = maxe
              reqrange = a,yesterday
          if reqrange[0] &gt;= reqrange[1]:
              print 'skipping daily',sym,'because we\'re up to date'
              continue
          print 'daily request range',sym,reqrange,reqrange[0] &gt; reqrange[1]
          try:
              ndaysbefore = int(rollspec) # exception if it's 'noroll'
              print 'hist fetch for %s, %i days' % (sym,ndaysbefore)
              rolldb.update_roll_db(blpcon,(sym,))
              names = rolldb.get_contract_range(sym,ndaysbefore,daily=True)
          except: names = {sym:None}
          # sort alphabetically here so oldest always gets done first
          #  (at least within the year)
          sorted_contracts = names.keys()
          sorted_contracts.sort()
          start,end = reqrange
          for contract in sorted_contracts:
              print 'partial fetch',contract,names[contract]
              if names[contract] == None:
                  _start,_end = start,end
              else:
                  da,db = names[contract]
                  dc,dd = start,end
                  try: _start,_end = get_overlap(da,db,dc,dd)
                  except: continue # because get_overlap returning None cannot assign to tuple
              _start = _start.strftime('%Y%m%d')
              _end = _end.strftime('%Y%m%d')
              logging.info('daily bars for %s (%s), %s - %s' % (sym,contract,_start,_end))
              result = get_daily(blpcon,(contract,),fields,_start,_end)
              try: result = result[contract]
              except:
                  print 'result doesn\'t contain requested symbol'
                  logging.error("ERROR: symbol '%s' not in daily request result" % contract)
                  # todo: log and alert error
                  continue
              if not 'date' in result:
                  print 'result has no date field'
                  logging.error('ERROR: daily result has no date field')
                  # todo: log and alert error
                  continue
              keys = result.keys()
              keys.remove('date')
              logging.info(' -- %i days returned' % len(result['date']))
              for i in range(len(result['date'])):
                  ordinal = datetime.fromtimestamp(int(result['date'][i])).toordinal()
                  for k in keys:
                      trysleep(c,'insert or ignore into daily (sid,fid,epoch,value) values (?,?,?,?)',(sid,fieldcodes[k],ordinal,result[k][i]))
              dbcon.commit()
  </code></pre>