Python падает, когда я обращаюсь к своей функции с помощью wxPython

Итак, у меня есть две части кода. Первый — это класс GUI:

'''
Created on Mar 6, 2013

@author: Zach
'''
# -*- coding: utf-8 -*- 

###########################################################################
## Python code generated with wxFormBuilder (version Sep  8 2010)
## http://www.wxformbuilder.org/
##
## PLEASE DO "NOT" EDIT THIS FILE!
###########################################################################

import wx
import wx.grid
from Books import *
###########################################################################
## Class MyFrame1
###########################################################################

class MyFrame1 ( wx.Frame ):

    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 734,344 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )

        self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )

        bSizer1 = wx.BoxSizer( wx.VERTICAL )

        bSizer2 = wx.BoxSizer( wx.HORIZONTAL )

        self.patrons_table = wx.grid.Grid( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0 )

        # Grid
        self.patrons_table.CreateGrid( 0, 7 )
        self.patrons_table.EnableEditing( True )
        self.patrons_table.EnableGridLines( True )
        self.patrons_table.SetGridLineColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_APPWORKSPACE ) )
        self.patrons_table.EnableDragGridSize( True )
        self.patrons_table.SetMargins( 0, 0 )

        # Columns
        self.patrons_table.SetColSize( 0, 100 )
        self.patrons_table.SetColSize( 1, 100 )
        self.patrons_table.SetColSize( 2, 100 )
        self.patrons_table.SetColSize( 3, 100 )
        self.patrons_table.SetColSize( 4, 100 )
        self.patrons_table.SetColSize( 5, 100 )
        self.patrons_table.SetColSize( 6, 100 )
        self.patrons_table.EnableDragColMove( True )
        self.patrons_table.EnableDragColSize( True )
        self.patrons_table.SetColLabelSize( 40 )
        self.patrons_table.SetColLabelValue( 0, "ID" )
        self.patrons_table.SetColLabelValue( 1, "Name" )
        self.patrons_table.SetColLabelValue( 2, "Address" )
        self.patrons_table.SetColLabelValue( 3, "Phone" )
        self.patrons_table.SetColLabelValue( 4, "Email" )
        self.patrons_table.SetColLabelValue( 5, "Fees/Day")
        self.patrons_table.SetColLabelValue( 6, "Fees Owed" )

        self.patrons_table.SetColLabelAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE )

        # Rows
        self.patrons_table.AutoSizeRows()
        self.patrons_table.EnableDragRowSize( True )
        self.patrons_table.SetRowLabelSize( 80 )
        self.patrons_table.SetRowLabelAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE )

        # Label Appearance

        # Cell Defaults
        self.patrons_table.SetDefaultCellAlignment( wx.ALIGN_LEFT, wx.ALIGN_TOP )
        self.patrons_table.SetToolTipString( u"Table of patrons in the library" )

        bSizer2.Add( self.patrons_table, 7, wx.EXPAND|wx.ALL|wx.ALIGN_BOTTOM, 5 )

        bSizer6 = wx.BoxSizer( wx.VERTICAL )

        self.m_panel1 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
        bSizer6.Add( self.m_panel1, 1, wx.EXPAND |wx.ALL, 5 )

        self.m_button1 = wx.Button( self, wx.ID_ANY, u"Add", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.m_button1.SetToolTipString( u"Adds a patron" )

        bSizer6.Add( self.m_button1, 0, wx.ALL, 5 )

        self.m_button2 = wx.Button( self, wx.ID_ANY, u"Remove", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.m_button2.SetToolTipString( u"Removes the selected patron" )

        bSizer6.Add( self.m_button2, 0, wx.ALL, 5 )

        self.m_button3 = wx.Button( self, wx.ID_ANY, u"Update", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.m_button3.SetToolTipString( u"Updates the database" )

        bSizer6.Add( self.m_button3, 0, wx.ALL, 5 )

        bSizer2.Add( bSizer6, 1, wx.EXPAND, 5 )

        bSizer1.Add( bSizer2, 1, wx.EXPAND, 5 )

        bSizer5 = wx.BoxSizer( wx.HORIZONTAL )

        self.m_searchCtrl2 = wx.SearchCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size( 715,-1 ), 0 )
        self.m_searchCtrl2.ShowSearchButton( True )
        self.m_searchCtrl2.ShowCancelButton( False )
        bSizer5.Add( self.m_searchCtrl2, 0, wx.ALL|wx.EXPAND, 5 )

        bSizer1.Add( bSizer5, 0, wx.EXPAND, 5 )

        self.SetSizer( bSizer1 )
        self.Layout()

        self.Centre( wx.BOTH )

        # Connect Events
        self.patrons_table.Bind( wx.grid.EVT_GRID_CELL_CHANGE, self.onGridChange )
        self.patrons_table.Bind( wx.grid.EVT_GRID_SELECT_CELL, self.onLeftClick )
        self.m_button1.Bind( wx.EVT_BUTTON, self.addpatron )
        self.m_button2.Bind( wx.EVT_BUTTON, self.removepatron )
        self.m_button3.Bind( wx.EVT_BUTTON, self.updatepatronsDatabase )
        self.m_searchCtrl2.Bind( wx.EVT_SEARCHCTRL_SEARCH_BTN, self.searchpatrons )
        self.m_searchCtrl2.Bind( wx.EVT_TEXT_ENTER, self.searchpatrons )


        #Import the Database into the table
        self.lib = Library()
        self.db = Database()
        for i in self.db.getPatrons():
            print "hello"
            self.lib.addPatron(Patron(i[0], i[1], i[2], i[3], i[4]))
        self.lib.resetHistory()


        for i in self.lib.patrons:
            self.patrons_table.InsertRows()
            self.patrons_table.SetCellValue(0,0,str(i["title"]))
            self.patrons_table.SetCellValue(0,1,str(i["author"]))
            self.patrons_table.SetCellValue(0,2,str(i["patron_id"]))
            self.patrons_table.SetCellValue(0,3,str(i["location"]))
            self.patrons_table.SetCellValue(0,4,str(i["publisher"]))
            self.patrons_table.SetCellValue(0,5,str(i["genre"]))
            self.patrons_table.SetCellValue(0,6,str(i["copy_right"]))
            self.patrons_table.SetCellValue(0,7,str(i["subject"]))
            self.patrons_table.SetCellValue(0,8,str(i["is_checked_out"]))
    def __del__( self ):
        pass


    # Virtual event handlers, overide them in your derived class

#EVENTS
    def onGridChange( self, event ):# Called if one of the cell values was changed
        updated_patron = Patron(self.patrons_table.GetCellValue(self.patrons_table.GetGridCursorRow(),0),
                             self.patrons_table.GetCellValue(self.patrons_table.GetGridCursorRow(),1),
                             self.patrons_table.GetCellValue(self.patrons_table.GetGridCursorRow(),2),
                             self.patrons_table.GetCellValue(self.patrons_table.GetGridCursorRow(),3),
                             self.patrons_table.GetCellValue(self.patrons_table.GetGridCursorRow(),4),
                             self.patrons_table.GetCellValue(self.patrons_table.GetGridCursorRow(),5),
                             self.patrons_table.GetCellValue(self.patrons_table.GetGridCursorRow(),6),
                             self.patrons_table.GetCellValue(self.patrons_table.GetGridCursorRow(),7),
                             self.patrons_table.GetCellValue(self.patrons_table.GetGridCursorRow(),8),
                             self.patrons_table.GetCellValue(self.patrons_table.GetGridCursorRow(),9),
                             self.patrons_table.GetCellValue(self.patrons_table.GetGridCursorRow(),10))
        self.lib.editPatron(self.selected_patron, updated_patron)
    def onLeftClick( self, event ): #Turns the selected row into a patron
        self.selected_patron = Patron(self.patrons_table.GetCellValue(self.patrons_table.GetGridCursorRow(),0),
                             self.patrons_table.GetCellValue(self.patrons_table.GetGridCursorRow(),1),
                             self.patrons_table.GetCellValue(self.patrons_table.GetGridCursorRow(),2),
                             self.patrons_table.GetCellValue(self.patrons_table.GetGridCursorRow(),3),
                             self.patrons_table.GetCellValue(self.patrons_table.GetGridCursorRow(),4),
                             self.patrons_table.GetCellValue(self.patrons_table.GetGridCursorRow(),5),
                             self.patrons_table.GetCellValue(self.patrons_table.GetGridCursorRow(),6),
                             self.patrons_table.GetCellValue(self.patrons_table.GetGridCursorRow(),7),
                             self.patrons_table.GetCellValue(self.patrons_table.GetGridCursorRow(),8),
                             self.patrons_table.GetCellValue(self.patrons_table.GetGridCursorRow(),9),
                             self.patrons_table.GetCellValue(self.patrons_table.GetGridCursorRow(),10))
        self.row = self.patrons_table.GetGridCursorRow()
        self.column = self.patrons_table.GetGridCursorCol()
        event.Skip()
    def addpatron( self, event ):# adds a patron to the library and the table
        self.patrons_table.InsertRows()
        self.lib.addpatron(Patron())
        event.Skip()
    def removepatron( self, event ): #removes a patron from the table and the library
        self.lib.removepatron(self.selected_patron)
        self.patrons_table.DeleteRows()
        print self.lib.patrons
        event.Skip()
    def updatepatronsDatabase( self, event ): #syncs the database with the library
        self.db.mergeWithLibrary(self.lib)

    def searchpatrons( self, event ):
        value =  self.m_searchCtrl2.GetValue()
        i=0
        while self.patrons_table.GetNumberRows()-1 >i:
            if self.patrons_table.GetCellValue(i,2) == value:
                self.patrons_table.SetGridCursor(i,2)
                self.patrons_table.SelectRow(i)
                self.patrons_table.Scroll(i,i)
                break
            i = i+1
if __name__ == '__main__':
    app = wx.PySimpleApp()
    frame = MyFrame1(None)
    frame.Show()
    frame.Maximize()
    app.MainLoop()

И вторая часть кода — это движок класса GUI:

'''
Created on Mar 2, 2013

@author: Braden

This is a test file to try to make the GUI easier to program
It worked!
'''

import sqlite3 as sq
class Book(object):
    r"""
    This class defines what a book is. All books in the library are book objects
    """
    def __init__(self, title = "n", author = "n", book_id = "n", location = "n", publisher = "n", genre = "n", copy_right = "n", subject = "n", is_checked_out = "n", price = "n", fee_increment = "n"):
        r"""
        This function sets the basic attributes of each book
        """
        self.attributes = {"title":title,
                          "author":author,
                          "book_id":book_id,
                          "location":location,
                          "publisher":publisher,
                          "genre":genre,
                          "copy_right":copy_right,
                          "subject": subject,
                          "is_checked_out":is_checked_out,
                          "price": price,
                          "fee_increment":fee_increment
                          }
    def __str__(self):
        r"""
        This returns a string representation of the book. This is what makes " print book" possible.
        """
        return str(self.attributes)
    def __getitem__(self,key):
        r"""
        This returns an attribute in the book. It makes "book['title']" work.
        """
        return self.attributes[key]
    def __setitem__(self,key,value):
        r"""
        This sets an attribute to a different value. It makes "book['title'] = 'My New Title' " Possilble ...I think.
        """
        self.attributes[key] = value
    def __cmp__(self,book):
        if self.attributes == book.attributes:
            return True
        else:
            return False      
class Patron(object):
    r"""
    This is the Patron class. It is almost identical to the Book class just with different attributes.
    """
    def __init__(self, patron_id, name, address, phone, email):
        self.attributes = { "patron_id" : patron_id,
                       "name" : name,
                       "address" : address,
                       "phone" : phone,
                       "email" : email,
                       "fee_balance" : 0.00,
                       "fees_per_day" : 0.00,
                       "books_checked_out" : "",
                       "books_overdue" : ""}
    def __str__(self):
        return str(self.attributes)
    def __getitem__(self,key):
        return self.attributes[key]
    def __setitem__(self,key,value):
        self.attributes[key] = value
class Library(object):
    r"""
    This is the Library Class. It manipulates a database that has been loaded into the RAM. 
    """
    def __init__(self):
        r"""
        All this does is set the default values for the two Loaded Databases and the history.
        """
        self.books = []
        self.patrons= []
        self.history = []
    def addBook(self,book):
        r"""
        This appends a book object to the self.books list. Then it appends the action to the self.history list.
        """
        self.books.append(book)
        self.history.append(("book","add",book))     
    def removeBook(self, Book):
        r"""
        This removes a book object from the self.books list. Then it appends the action to the self.history list
        """
        self.books.remove(Book)
        self.history.append(("book","remove",Book))  
    def editBook(self, old_book, new_book):
        original_id = old_book["book_id"]
        r"""
        This edits a book object in the self.books list. Then it appends the action to the self.history list.
        """
        old_book["title"] = new_book["title"]
        old_book["author"] = new_book["author"]
        old_book["book_id"] = new_book["book_id"]
        old_book["location"] = new_book["location"]
        old_book["publisher"] = new_book["publisher"]
        old_book["genre"] = new_book["genre"]
        old_book["copy_right"] = new_book["copy_right"]
        old_book["subject"] = new_book["subject"]
        old_book["is_checked_out"] = new_book["is_checked_out"]
        old_book["price"] = new_book["price"]
        old_book["fee_increment"] = new_book["fee_increment"]
        self.history.append(("book","edit",old_book,original_id))    
    def addPatron(self, patron):
        r"""
        This appends a new Patron object to the self.patrons list. It then appends the action to the self.history list.
        """
        self.patrons.append(patron)
        self.history.append(("patron","add",patron))
        print "bonjour"
        print self.patrons[0]
    def removePatron(self,patron):
        r"""
        This Removes a patron object from the self.patrons list. It then appends the actino to the self.history list.
        """
        self.patrons.remove(patron)
        self.history.append(("patron","remove",patron)) 
    def editPatron(self,patron,attribute,value):
        r"""
        This edits a patron object in the self.patrons list. It then appends the action to the self.history list.
        """
        patron[attribute] = value
        self.history.append(("patron","edit",patron))
    def resetHistory(self):
        r"""
        This resets the self.history list
        """
        self.history=[]
    def getBook(self,book_id):
        r"""
        This finds a book based on its id
        """
        for i in self.books:
            if i["book_id"] == str(book_id):
                return i

    def __str__(self):

        for i in self.books:
            print i
        for i in self.patrons:
            print i         
        return "done"
class Database():
    r"""
    This is the Database Class. It modifies the library.db file.
    """
    def __init__ (self):
        r"""
        This presets the self.database variable and the self.cursor variable
        """
        self.database = sq.connect('library.db')
        self.cursor = self.database.cursor()
    def mergeWithLibrary(self,library):
        r"""
        This is my personal favorite. It updates the library.db file based off of the changes the Library object.

        """
        for i in library.history:
            print i
            if i[0] == "book":
                if i[1] == "add":
                    self.addBook(i[2])
                elif i[1] == "remove":
                    self.deleteBook(i[2])
                elif i[1] == "edit":
                    self.editBook(i[2],i[3])
            elif i[0] == "patron":
                if i[1] == "add":
                    self.addPatron(i[2])
                elif i[1] == "remove":
                    self.deletePatron(i[2])
                elif i[2] == "edit":
                    self.editPatron(i[2])
        library.resetHistory()
    def getBooks(self):
        r"""
        This returns all of the books in the library.db database
        """
        self.cursor.execute("SELECT * FROM books")
        return self.cursor.fetchall()
    def getPatrons(self):
        r"""
        This returns all of the Patrons in the library.db database
        """
        self.cursor.execute("SELECT * FROM patrons")
        print self.cursor.fetchall()
        print "called"
        return [(0,0,0,0,0,0,0,0,0,0,0,0)]
    def editBook(self,Book,id):
        r"""
        This updates a Book
        """
        self.cursor.execute("UPDATE books SET title = '"+Book["title"]+"', author = '"+Book["author"]+"', book_id= '"+Book["book_id"]+"', location = '"+Book["location"]+"', publisher = '"+Book["publisher"]+"', genre = '"+Book["genre"]+"', copy_right = '"+Book["copy_right"]+"', subject = '"+Book["subject"]+"', is_checked_out = '"+Book["is_checked_out"]+"', price = '"+Book["price"]+"', fee_increment = '"+Book["fee_increment"]+"' WHERE book_id = '"+id+"'")

        self.database.commit()
        print Book["fee_increment"]
    def editPatron(self,Patron):
        r"""
        This edits a Patron
        """
        self.cursor.execute("UPDATE patrons SET name= '"+Patron["name"]+"', address = '"+Patron["address"]+"', phone = '"+str(Patron["phone"])+"', email = '"+Patron["email"]+"', fee_balance = '"+str(Patron["fee_balance"])+"', fees_per_day = '"+str(Patron["fees_per_day"])+"', books_checked_out = '"+Patron["books_checked_out"]+"', books_overdue = '" +Patron["books_overdue"]+"' WHERE id ="+str(Patron["patron_id"]))
        self.database.commit()
    def deleteBook(self,Book):
        r"""
        This deletes a book
        """
        self.cursor.execute("DELETE FROM books WHERE book_id = "+"'"+Book["book_id"]+"'")
        self.database.commit()
    def deletePatron(self,Patron):
        r"""
        """
        self.cursor.execute("DELETE FROM patrons WHERE id = "+"'"+str(Patron["patron_id"])+"'")
        self.database.commit()
    def addBook(self,Book):
        r"""
        This adds a book
        """
        data = [        
        Book["title"],
        Book["author"],
        Book["book_id"],
        Book["location"],
        Book["publisher"],
        Book["genre"],
        Book["copy_right"],
        Book["subject"],
        Book["is_checked_out"],
        Book["price"],
        Book["fee_increment"]
        ]
        self.cursor.execute("INSERT INTO books VALUES(?,?,?,?,?,?,?,?,?,?,?)", data)
        self.database.commit()
    def addPatron(self,Patron):
        r"""
        This adds a Patron
        """
        data = [Patron["patron_id"],
        Patron["name"],
        Patron["address"],
        Patron["phone"],
        Patron["email"],
        Patron["fee_balance"],
        Patron["fees_per_day"], 
        Patron["books_checked_out"], 
        Patron["books_overdue"]]
        self.cursor.execute("INSERT INTO patrons VALUES(?,?,?,?,?,?,?,?,?)",data)
        self.database.commit()

Каждый раз, когда я запускаю свой код, все мои маленькие флаги print появляются в консоли, но окно не открывается, а затем происходит сбой python. Комментирование оператора for, в котором я импортирую свою базу данных в таблицу, позволяет программе работать, но любые вызовы self.lib.addPatron снова приведут к сбою программы. Я не вижу проблем с этой функцией, я просто тупой?


person Zazzalicious    schedule 07.03.2013    source источник
comment
Вы, вероятно, не глупы, но здесь вы получите больше помощи, если сможете сократить свой код до более простого примера. Это может решить и вашу проблему!   -  person askewchan    schedule 07.03.2013
comment
Я знал, что это, вероятно, слишком долго, но я недостаточно продвинут, чтобы знать на 100%, как сократить код, чтобы можно было найти решение. Тем не менее, спасибо за ваш вклад! Это поможет в будущем.   -  person Zazzalicious    schedule 07.03.2013
comment
Ой! И я использую Python 2.6, если это кому-то важно.   -  person Zazzalicious    schedule 07.03.2013


Ответы (2)


Было бы полезно, если бы вы предоставили нам трассировку, которую вы получали. Когда я запускаю этот код, я получаю следующее:

  sqlite3.OperationalError: no such table: patrons
  File "c:\Users\mdriscoll\Desktop\brk.py", line 191, in <module>
    frame = MyFrame1(None)
  File "c:\Users\mdriscoll\Desktop\brk.py", line 115, in __init__
    for i in self.db.getPatrons():
  File "c:\Users\mdriscoll\Desktop\Books.py", line 184, in getPatrons
    self.cursor.execute("SELECT * FROM patrons")

Поскольку вы заявляете, что у вас тоже возникает проблема с «self.lib.addPatron», это означает, что это, вероятно, та же проблема. Как показывает трассировка, таблицы не существует. Вам нужно создать таблицу (даже если она пуста) ПРЕЖДЕ, чем вы сможете что-либо добавить для них. Эта статья может помочь вам начать работу: http://www.blog.pythonlibrary.org/2012/07/18/python-a-simple-step-by-step-sqlite-tutorial/

person Mike Driscoll    schedule 07.03.2013

При отладке программ WXpython, которые дают сбой до того, как вы получите какой-либо полезный вывод, вы можете сохранить ошибки в файл журнала, указав перенаправление при запуске приложения. Итак, изменив строку, которая запускает приложение, на:

app = wx.pySimpleApp(redirect=True,  filename="logfile.txt") 

сохранит ваши ошибки в файл журнала в той же папке, что и ваш сценарий, и тогда вы будете иметь лучшее представление о том, что происходит.

person waywardengineer    schedule 08.03.2013