2016-07-26 10 views
1

ich Teil einer Klasse, die wie folgt aussieht:Exception Druck nur ein Wort

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 

als Teil eines Tests der Fehlerbehandlung, habe ich versucht, ohne die set_new_mode Funktion aufrufen zuerst die Klassenvariable initialisiert self.keithley . In diesem Fall würde ich erwarten, dass die print self.keithley Anweisung eine AttributeError: keithgui instance has no attribute 'keithley' auslösen würde. Die print e und self.print_to_log('\nERROR:set_new_mode: %s' % e) geben jedoch an, dass e nur das Wort "keithley" enthält.

Die Änderung print e zu print type(e) zeigt, dass e immer noch den Typ AttributeError hat, aber die Variable enthält keine nützlichen Informationen mehr über die Ausnahme. Warum? Und wie gebe ich e zu seiner erwarteten Form zurück?

Edit: Hier ist eine MEW, um den Fehler zu reproduzieren. Um den Fehler zu reproduzieren, starten Sie die GUI, ändern Sie den Modus auf etwas anderes als VOLT und klicken Sie auf die Schaltfläche Update.

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

können Sie minimalen Code zur Verfügung stellen, um das Problem zu reproduzieren, damit wir sehen können, ob wir das gleiche Problem sehen? – depperm

+0

Vielleicht möchten Sie das 'Logging'-Modul auschecken - insbesondere' logging.exception() 'ist super nützlich –

+0

Ich kann das nicht reproduzieren, bekomme ich' ERROR: set_new_mode: Fnord-Instanz hat kein Attribut 'keithley' Fnord-Instanz hat kein Attribut 'keithley'' –

Antwort

1

Wenn Sie Ihren Code ändern:

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') 

Und dann beginnt mit s Schreiten durch, sehen Sie, dass eine auf dem Fenster __getattr__ Funktion gibt. Ich schaue durch, um zu sehen, was das Problem jetzt verursacht, aber das wird effektiv deine Antwort sein.


den Call-Stack Folgen, es führte mich zu einem Anruf self.tk = _tkinter.create, die mich schließlich here bekommen geführt. Letztendlich läuft das darauf hinaus, dass die Ausnahme in C-Territorium passiert, also produziert es eine andere AttributeError Nachricht.

+0

Also in diesem Fall scheint es, dass die Lösung ist über '' 'hasattr (self, 'keithley')' '' zuerst nach '' 'self.keithley''' suchen und dann einen AttributeError auslösen, falls dieser noch nicht initialisiert wurde (mit einer Art nützliche Fehlermeldung für den Benutzer). Ich werde voran gehen und dies als die Antwort markieren, da es scheint, dass dies durch die Implementierung von Tk verursacht wird, anstatt meinen Code, so dass die Problemumgehung ist etwas wie das, was ich oben gepostet. – Nick

+1

Sie könnten jederzeit einen "getattr" in * Ihren * Code einfügen und ihn dann durch den Stapel laufen lassen. Warum sollte "keithley" nicht gleich zu Beginn etwas Sinnvolles machen? [Zeitliche Kopplung] (http://blog.ploeh.dk/2011/05/24/DesignSmellTemporalCoupling/) sollte nach Möglichkeit vermieden werden. –

+0

'keithley' ist eigentlich eine Klasse, die die Maschinerie für Python enthält, um mit einem Instrument über RS232 zu sprechen. Der Zweck der GUI besteht darin, die von der keithley gezogenen Daten anzuzeigen/zu manipulieren.Das Problem besteht darin, dass manchmal mehrere keithleys mit einer Maschine verbunden sind und die GUI sich mit einer bestimmten Verbindung verbinden möchte, die vom Benutzer zum Zeitpunkt der Verbindung eingestellt wurde (kann also nicht im Voraus definieren). Ich könnte etwas wie set '' 'self.keithley = None''' machen und' '' wenn self.keithley == None: raise ... '' 'überprüfen, aber ist das nicht das Gleiche wie das Überprüfen ob es existiert? Würden Sie die Implementierung empfehlen? – Nick