<type'exception.ioerror'=“”> [Errno 9]错误的文件描述符</type>

时间:2014-06-19 22:09:23

标签: python ioerror

以下代码是程序的一部分,旨在从Bloomberg终端捕获数据并将其转储到SQLite数据库中。它在我的32位Windows XP上运行得很好。但它一直在给我 64位Windows 7上的“get_history.histfetch错误:[Errno 9]错误文件描述符”,尽管在64位操作系统下使用32位python应该没有问题。有时这个问题可以通过退出程序并再次打开它来解决,但有时它只是不起作用。现在我真的很困惑导致这个问题的原因。我查看了源代码,发现问题是在调用“histfetch”时生成的,我不知道代码的哪一部分失败了。有人可以帮我从这里出去吗...?我真的很感激。提前谢谢。

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 < datetime.fromordinal(unionrange[0]): a = oldestdaily
            else: a = maxe
            reqrange = a,yesterday
        if reqrange[0] >= reqrange[1]:
            print 'skipping daily',sym,'because we\'re up to date'
            continue
        print 'daily request range',sym,reqrange,reqrange[0] > 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()

1 个答案:

答案 0 :(得分:1)

打印完整的回溯,而不仅仅是异常消息。回溯将显示引发异常的位置,以及问题所在:

import traceback

...

    try: self.histfetch()
    except Exception,e:
        logging.error('get_history.histfetch error: %s %s' % (str(type(e)),str(e)))
        logging.error(traceback.format_exc())
        if self.errornotify != None:
            self.errornotify('get_history error','%s %s' % ( str(type(e)), str(e) ) )

更新:

通过以上(或类似的,想法是查看完整的追溯),你说:

  

它说这是“打印”功能。禁用所有“打印”功能后,该程序运行良好。

{post}使用的print函数调用只在python 2.x中有效。如果你正在使用它,那么运行你的脚本的应用程序可能是未定义的print并且你应该使用日志函数,否则我看不出调用有什么问题(除非你的意思是只有一个)印刷品是问题,然后我需要看到确切的错误来识别 - 发布这个,如果你想弄清楚这一点)。如果您使用的是Python 3.x,则必须使用print(a, b, c, ...),请参阅3.x文档。