2016-07-26 4 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 e и self.print_to_log('\nERROR:set_new_mode: %s' % e) указывают, что e содержит только слово «keithley».

Изменение print e до print type(e) показывает, что e все еще имеет тип AttributeError, но переменная больше не содержит никакой полезной информации об исключении. Зачем? И как мне вернуть e в ожидаемую форму?

Редактировать: здесь есть MEW для воспроизведения ошибки. Чтобы воспроизвести ошибку, запустите графический интерфейс, измените режим на что-то другое, кроме 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

Так что в этом случае кажется, что решение чтобы проверить существование '' 'self.keithley''' сначала через' '' hasattr (self, 'keithley') '' ', а затем поднять AttributeError, если он еще не был инициализирован (с каким-то полезное сообщение об ошибке для пользователя). Я собираюсь продолжить и отметить это как ответ, так как кажется, что это связано с реализацией Tk, а не с моим кодом, поэтому обходной путь - это то, что я написал выше. – Nick

+1

Вы всегда можете добавить код 'getattr' в * ваш *, а затем позволить ему просачивать стек. Однако почему бы не просто установить 'keithley' что-то разумное в начале? [Временное соединение] (http://blog.ploeh.dk/2011/05/24/DesignSmellTemporalCoupling/) следует избегать, если это возможно. –

+0

«keithley» на самом деле является классом, который содержит механизмы для работы python с прибором через RS232. Целью графического интерфейса является отображение/обработка данных, взятых из кейтли.Проблема в том, что иногда к компьютеру подключаются несколько кэйтлей, и GUI хочет подключиться к определенному, установленному пользователем во время соединения (поэтому не может определить заранее). Я мог бы сделать что-то вроде set '' 'self.keithley = None''' и проверить' '' if self.keithley == None: raise ... '' ', но это не то же самое, что и проверка, если это существует? Так вы бы рекомендовали его реализовать? – Nick

Смежные вопросы