2016-07-26 77 views
1

我有一个类,看起来像这样的部分:异常打印只有一个字

def set_new_mode(self,mode): 
    try: 
     #this will fail, since self.keithley is never initialized 
     print self.keithley 
     self.keithley.setzerocheck(on=True) 
     self.keithley.selectmode(mode,nplc=6) 
     self.keithley.setzerocheck(on=False) #keithcontrol class will 
     #automatically turn on zero correction when zchk is disabled 
     self.mode = mode 
     self.print_to_log('\nMode set to %s' % self.mode) 
    except Exception as e: 
     self.print_to_log('\nERROR:set_new_mode: %s' % e) 
     print e 

由于错误处理某些测试的一部分,我已经打过电话了set_new_mode功能,无需首先初始化类变量self.keithley 。在这种情况下,我认为print self.keithley声明会提高AttributeError: keithgui instance has no attribute 'keithley'。但是,print eself.print_to_log('\nERROR:set_new_mode: %s' % e)指示e仅包含单词“keithley”。

print e更改为print type(e)表明e仍具有AttributeError类型,但该变量不再包含有关该异常的任何有用信息。为什么?我该如何将e返回到预期的形式?

编辑:这是一个水电部重现错误。 要重现错误,请启动GUI,将模式更改为VOLT以外的其他模式,然后单击更新按钮。

import Tkinter 

import numpy as np 
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg 


class keithgui(Tkinter.Tk): 
    def __init__(self,parent): 
     Tkinter.Tk.__init__(self,parent) 
     self.parent = parent 
     self.initialize() 

    def initialize(self): 
     #we are not initially connected to the keithley 
     self.connected = False 
     self.pauseupdate = False 

     #set up frames to distribute widgets 
     #MASTER FRAME 
     self.mframe = Tkinter.Frame(self,bg='green') 
     self.mframe.pack(side=Tkinter.TOP,fill='both',expand=True) 
     #LEFT AND RIGHT FRAMES 
     self.Lframe = Tkinter.Frame(self.mframe,bg='red',borderwidth=2,relief='raised') 
     self.Lframe.pack(side='left',fill='both',expand=True) 
     self.Rframe = Tkinter.Frame(self.mframe,bg='blue',borderwidth=2,relief='raised') 
     self.Rframe.pack(side='right',fill='both',expand=False) 

     #create the log text widget to keep track of what we did last 
     #also give it a scrollbar... 
     scrollbar = Tkinter.Scrollbar(master=self.Lframe) 
     scrollbar.pack(side=Tkinter.RIGHT,anchor='n') 
     self.logtext = Tkinter.Text(master=self.Lframe,height=3,yscrollcommand=scrollbar.set) 
     scrollbar.config(command=self.logtext.yview) 
     self.logtext.pack(side=Tkinter.TOP,anchor='w',fill='both') 

     #Button to update all settings 
     updatebutton = Tkinter.Button(master=self.Rframe,text='Update',command=self.update_all_params) 
     updatebutton.grid(column=2,row=0) 


     #Option menu & label to select mode of the Keithley 
     modes = ['VOLT','CHAR','CURR'] 
     modelabel = Tkinter.Label(master=self.Rframe,text='Select Mode:') 
     modelabel.grid(column=0,row=2,sticky='W') 
     self.mode = 'VOLT' 
     self.modevar = Tkinter.StringVar() 
     self.modevar.set(self.mode) 
     modeselectmenu = Tkinter.OptionMenu(self.Rframe,self.modevar,*modes) 
     modeselectmenu.grid(column=1,row=2,sticky='W') 

    def print_to_log(self,text,loc=Tkinter.END): 
     self.logtext.insert(loc,text) 
     self.logtext.see(Tkinter.END) 



    def update_all_params(self): 
     self.set_refresh_rate() 
     if self.modevar.get() != self.mode: 
      self.set_new_mode(self.modevar.get()) 
     else: 
      self.print_to_log('\nAlready in mode %s' % self.mode) 

    def set_refresh_rate(self): 
     try: 
      self.refreshrate = np.float(self.refreshrateentryvar.get()) 
      self.print_to_log('\nRefresh rate set to %06.3fs' % self.refreshrate) 
     except Exception as e: 
      self.print_to_log('\nERROR:set_referesh_rate: %s' % e) 

    def set_new_mode(self,mode): 
     try: 
      print self.keithley 
      self.keithley.setzerocheck(on=True) 
      self.keithley.selectmode(mode,nplc=6) 
      self.keithley.setzerocheck(on=False) #keithcontrol class will 
      #automatically turn on zero correction when zchk is disabled 
      self.mode = mode 
      self.print_to_log('\nMode set to %s' % self.mode) 
     except Exception as e: 
      self.print_to_log('\nERROR:set_new_mode: %s' % e) 
      print e 
      print type(e) 

if __name__ == "__main__": 
    app = keithgui(None) 
    app.title('Keithley GUI') 
    app.mainloop() 
+0

你能提供最少的代码来重现问题吗,所以我们可以看到我们是否看到同样的问题? – depperm

+0

您可能想查看'logging'模块 - 特别是'logging.exception()'是非常有用的 –

+0

我不能再现这个,我得到'ERROR:set_new_mode:Fnord实例没有属性'keithley' Fnord实例没有属性'keithley'' –

回答

1

如果您修改代码:

import Tkinter as tk 

class Fnord(tk.Tk): 
    def set_new_mode(self,mode): 
     try: 
      import pdb; pdb.set_trace() 
      #this will fail, since self.keithley is never initialized 
      print self.keithley 

Fnord().set_new_mode('whatever') 

,然后开始加紧通过与s,你会看到有你的窗口上__getattr__功能。我正在仔细查看现在导致问题的原因,但这实际上就是您的答案。


继调用堆栈,这导致我打电话self.tk = _tkinter.create,最终导致我得到here。归根结底,这个例外发生在C领域,所以它产生了不同的AttributeError消息。

+0

因此,在这种情况下,似乎解决方案是首先通过'''hasattr(self,'keithley')'''检查self.keithley''是否存在,然后在没有初始化的时候引发一个AttributeError(用某种对用户有用的错误消息)。 我打算继续,并将其标记为答案,因为看起来这是由Tk的实现而非我的代码引起的,所以解决方法就像我上面发布的那样。 – Nick

+1

你可以随时在*你的*代码中添加一个'getattr',然后让它穿透堆栈。但是,为什么不在开始时将'keithley'设置为合理的呢?如果可能,应避免[时间耦合](http://blog.ploeh.dk/2011/05/24/DesignSmellTemporalCoupling/)。 –

+0

'keithley'实际上是一个包含python机器的类,通过RS232与仪器对话。 GUI的目的是显示/处理从吉时利绘制的数据。问题是,有时候有多个keithleys连接到一台机器,并且GUI想要连接到用户在连接时设置的特定连接(所以不能提前定义)。我可以做一些像'''self.keithley = None''',并检查'''如果self.keithley == None:raise ...''',但与检查它是否基本相同存在?这是你如何建议实施它? – Nick