SystemError in Learning Python Example

kopecjc kopecjc at worldnet.att.net
Tue Dec 21 00:33:38 EST 1999


I have been trying to run the example, contained in Chapter 10 of Lutz
and Ascher's Learning Python (pp. 288-293), entitled "A Tkinter-Based
GUI Editor for Managing Form Data", but have been experiencing problems
-- basically, the Tkinter widget appears on the screen, with labels but
without any of the information that was supposed to be displayed in the
listbox, and I get a message to the output window that includes the
statement "SystemError: Failed to import class FeedbackData from module
__main__".  (The full output message, as well as the full code, is set
forth below should anyone care to take a look.)  I realize there were
several typos and bugs in the book (which were reflected on the "Errata"
web page), and I have corrected in them my version.  I have also made
several other tweaks to the code, but I do not think my tweaks were the
problem.  I am pretty sure that all the required files on the right
paths.  Does anyone know what could be causing the "SystemError"
message?  I would have thought that FeedbackData is from module
feedback, not __main__.  Does anyone have any idea why the pickle module
would have expected it to be from __main__?  I have tried tracking this
down with the debug feature in IDLE without any luck.  Am I missing an
"import" statement in module FormEditor?  I have also tried out a
variety of from/imports, but again no luck.  Any thoughts or suggestions
would be much appreciated.  Thanks in advance.

*********************

The output window reads as follows:

Traceback (innermost last):
  File "/usr/lib/python1.5/site-packages/idle/ScriptBinding.py", line
131, in run_module_event
    execfile(filename, mod.__dict__)
  File "/usr/lib/python1.5/feedbackeditor.py", line 6, in ?
    FormEditor("Feedback Editor", FeedbackData,
r"/usr/local/apache/logs/feedback")
  File "/usr/lib/python1.5/FormEditor.py", line 37, in __init__
    self.load_data()
  File "/usr/lib/python1.5/FormEditor.py", line 55, in load_data
    item = pickle.load(open(os.path.join(self.storagedir, filename),
'r'))
  File "/var/tmp/python-root/usr/lib/python1.5/pickle.py", line 826, in
load
    return Unpickler(file).load()
  File "/var/tmp/python-root/usr/lib/python1.5/pickle.py", line 495, in
load
    dispatch[key](self)
  File "/var/tmp/python-root/usr/lib/python1.5/pickle.py", line 612, in
load_inst
    klass = self.find_class(module, name)
  File "/var/tmp/python-root/usr/lib/python1.5/pickle.py", line 669, in
find_class
    raise SystemError, \
SystemError: Failed to import class FeedbackData from module __main__

***********************

The feedbackeditor module reads as follows:

# file feedbackeditor.py (Tkinter)

from FormEditor import FormEditor
from feedback import FeedbackData, FormData
from Tkinter import mainloop
FormEditor("Feedback Editor", FeedbackData,
r"/usr/local/apache/logs/feedback")
mainloop()

**********************

The FormEditor module reads as follows:

# file FormEditor

from Tkinter import *
import string, os, pickle

class FormEditor:
    def __init__(self, name, dataclass, storagedir):
        self.storagedir = storagedir      # stash away some references
        self.dataclass = dataclass
        self.row = 0
        self.current = None

        self.root = root = Tk()           # create window and size it
        root.minsize(300,200)

        root.rowconfigure(0, weight=1)    # define how columns and rows
scale
        root.columnconfigure(0, weight=1) # when the window is resized
        root.columnconfigure(1, weight=2)

        # create the title Label
        Label(root, text=name, font='bold').grid(columnspan=2)
        self.row = self.row + 1

        # create the main listbox and configure it
        self.listbox = Listbox(root, selectmode=SINGLE)
        self.listbox.grid(columnspan=2,sticky=E+W+N+S)
        self.listbox.bind('<ButtonRelease-1>', self.select)
        self.row = self.row + 1

        # call self.add_variable once per variable in the class's
fieldnames var
        for fieldname in dataclass.fieldnames:
            setattr(self, fieldname, self.add_variable(root, fieldname))

        # create a couple of buttons, with assigned commands
        self.add_button(self.root, self.row, 0, 'Delete Entry',
self.delentry)
        self.add_button(self.root, self.row, 1, 'Reload',
self.load_data)
        self.load_data()

    def add_variable(self, root, varname): 
        Label(root, text=varname).grid(row=self.row, column=0, sticky=E)
        value = Label(root, text='', background='gray90',
                      relief=SUNKEN, anchor=W, justify=LEFT)
        value.grid(row=self.row, column=1, sticky=E+W)
        self.row = self.row + 1
        return value

    def add_button(self, root, row, column, text, command):
        button = Button(root, text=text, command=command)
        button.grid(row=row, column=column, sticky=E+W, padx=5, pady=5)

    def load_data(self):
        self.listbox.delete(0,END)
        self.items = []
        for filename in os.listdir(self.storagedir):
            item = pickle.load(open(os.path.join(self.storagedir,
filename), 'r'))
            item._filename = filename
            self.items.append(item)
            self.listbox.insert('end', `item`)
        self.listbox.select_set(0)
        self.select(None)

    def select(self, event):
        selection = self.listbox.curselection()
        self.selection = self.items[int(selection[0])]
        for fieldname in self.dataclass.fieldnames:
            label = getattr(self, fieldname)                # GUI field
            labelstr = getattr(self.selection, fieldname)   # instance
attribute
            #labelstr = string.replace(labelstr,'\r', '')
            label.config(text=labelstr)

    def delentry(self):
       
os.remove(os.path.join(self.storagedir,self.selection._filename))
        self.load_data()

*********************

The feedback module reads as follows:

#!/usr/bin/python

import cgi, os, sys, string

def gush(data):
    print "Content-type: text/html\n"
    print "<h3>Thanks, %(name)s!</h3>" % vars(data)
    print "Our customer's comments are always appreciated."

def whimper(data):
    print "Content-type: text/html\n"
    print "<h3>Sorry, %(name)s!</h3>" % vars(data)
    print "We're very sorry to read that you had a complaint."

def bail():
    print "Content-type: text/html\n"
    print "<h3>Error filling out form!</h3>"
    print "Please fill in all the fields in the form.<p>"
    print '<a href="http://localhost/hello2.html">'
    print 'Go back to the form!</a>'
    sys.exit()

class FormData:
    """ A repository for information gleaned from a CGI form. """
    def __init__(self, formdict):
        for fieldname in self.fieldnames:
            if not form.has_key(fieldname) or form[fieldname].value ==
"":
                bail()
            else:
                setattr(self, fieldname, form[fieldname].value)

class FeedbackData(FormData):
    """ A FormData generated by the hello2.html form. """
    fieldnames = ('name', 'address', 'email', 'type', 'text')
    def __repr__(self):
        return "%(type)s from %(name)s on %(time)s" % vars(self)

DIRECTORY = r'/usr/local/apache/logs/feedback'

if __name__ == '__main__':
    sys.stderr = sys.stdout
    form = cgi.FieldStorage()
    data = FeedbackData(form)
    if data.type == 'comment':
        gush(data)
    else:
        whimper(data)

    # save the data to file
    import tempfile, pickle, time
    tempfile.tempdir = DIRECTORY
    data.time = time.asctime(time.localtime(time.time()))
    pickle.dump(data, open(tempfile.mktemp(), 'w'))

*********************



More information about the Python-list mailing list