我对python不是很好,但对于这个项目,我需要使用python GUI来测试我的程序。它的编译没有任何错误,但当我在GUI中测试它时,它会出现错误。该程序的目标是从一个包含所有翻译/定义的.txt文件创建一个英法词典。我的代码如下。如果有人能帮忙,那就太好了。
这些是我得到的错误:
Exception in Tkinter callback
Traceback (most recent call last):
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1470, in __call__
return self.func(*args)
File "Dictionary.py", line 33, in <lambda>
lambda e, s=self: s.translate(english, french))
File "Dictionary.py", line 69, in translate
clearall(english, french)
NameError: global name 'clearall' is not defined
要了解更多信息,我应该检查以下条件:1) 没有命令行参数和2)文件打开失败。
Dictionary.cpp:
#include "HashTable.h"
#include "DictionaryEntry.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
int main( int argc, char** argv )
{
HashTable <DictionaryEntry> table;
DictionaryEntry dictEntry;
string temp;
string entry;
string translation;
vector <string> engWords;
string uentry;
int randNum;
ifstream inputStream;
//If command line is empty, error
if( argc <= 1)
{
cout << "Invalid entry." << endl;
return 0;
}
inputStream.open(argv[1]);
//If no file is opened, error
/*if( !inputStream )
{
cout << "Invalid file." << endl;
return 0;
}*/
while( !inputStream.eof( ) )
{
getline( inputStream, temp );
unsigned location = temp.find_first_of( 't' );
entry = temp.substr( 0, location );
int end = temp.length( );
translation = temp.substr( location + 1, end );
dictEntry.set( entry, translation );
table.insert( dictEntry );
engWords.push_back( entry );
}
while( 1 )
{
cout << "Insert english word: ";
cin >> uentry;
DictionaryEntry search;
search.set( uentry, "");
if( uentry == "random" )
{
randNum = rand( ) % engWords.size( );
temp = engWords.at( randNum );
search.set( temp, "" );
dictEntry = table.retrieve( search );
cout << dictEntry.getEntry( ) << endl;
cout << dictEntry.getTranslation( ) << endl;
}
else
{
dictEntry = table.retrieve( search );
if( dictEntry.getEntry( ) != "" )
{
cout << dictEntry.getEntry( ) << endl;
cout << dictEntry.getTranslation( ) << endl;
}
else
{
cout << "n";
cout << "n";
}
}
}
}
List.h:
#ifndef LIST_H
#define LIST_H
using namespace std;
template <typename Object>
class List
{
private:
struct Node
{
Object data;
Node *prev;
Node *next;
Node(const Object & d = Object{ }, Node * p = nullptr, Node * n = nullptr )
: data{ d }, prev{ p }, next{ n } { }
Node( Object && d, Node * p = nullptr, Node * n = nullptr )
: data{ std::move( d ) }, prev{ p }, next{ n } { }
};
public:
class const_iterator
{
public:
const_iterator( ) : current{ nullptr }
{ }
const Object & operator* ( ) const
{ return retrieve( ); }
const_iterator & operator++ ( )
{
current = current->next;
return *this;
}
const_iterator operator++ (int)
{
const_iterator old = *this;
++( *this );
return old;
}
bool operator== (const const_iterator & rhs ) const
{ return current == rhs.current; }
bool operator!= ( const const_iterator & rhs ) const
{ return !( *this == rhs ); }
protected:
Node *current;
Object & retrieve( ) const
{return current->data;}
const_iterator(Node *p ) : current{ p }
{ }
friend class List<Object>;
};
class iterator : public const_iterator
{
public:
iterator( )
{ }
Object & operator* ( )
{ return const_iterator::retrieve( ); }
const Object & operator* ( ) const
{ return const_iterator::operator*( ); }
iterator & operator++ ( )
{
this->current = this->current->next;
return *this;
}
iterator operator++ ( int )
{
iterator old = *this;
++( *this );
return old;
}
iterator operator--()
{
const_iterator::current = const_iterator::current->prev;
return *this;
}
iterator operator--(int)
{
iterator old = *this;
--(*this);
return old;
}
protected:
iterator( Node *p ) : const_iterator{ p }
{ }
friend class List<Object>;
};
public:
List( )
{ init( ); }
~List( )
{
clear( );
delete head;
delete tail;
}
List( const List & rhs )
{
init( );
for( auto & x : rhs )
push_back( x );
}
List & operator= ( const List & rhs )
{
List copy = rhs;
std::swap( *this, copy );
return *this;
}
List ( List && rhs )
: theSize{ rhs.theSize }, head{rhs.head }, tail{rhs.tail }
{
rhs.theSize = 0;
rhs.head = nullptr;
rhs.tail = nullptr;
}
List & operator= ( List && rhs )
{
std::swap( theSize, rhs.theSize );
std::swap( head, rhs.head );
std::swap( tail, rhs.tail );
return *this;
}
iterator begin( )
{ return { head->next }; }
const_iterator begin( ) const
{ return { head->next }; }
iterator end( )
{ return { tail }; }
const_iterator end( ) const
{ return { tail }; }
int size( ) const
{ return theSize; }
bool empty( ) const
{ return size( ) == 0; }
void clear( )
{
while( !empty( ) )
pop_front( );
}
Object & front( )
{ return *begin( ); }
const Object & front( ) const
{ return *begin( ); }
Object & back( )
{ return *--end( ); }
const Object & back( ) const
{ return *--end( ); }
void push_front( const Object & x )
{ insert( begin( ), x ); }
void push_front( Object && x )
{ insert( begin( ), std::move( x ) ); }
void push_back( const Object & x )
{ insert( end( ), x ); }
void push_back( Object && x )
{ insert( end( ), std::move( x ) ); }
void pop_front( )
{ erase( begin( ) ); }
void pop_back( )
{ erase( --end( ) ); }
//Insert x before itr
iterator insert( iterator itr, const Object & x )
{
Node *p = itr.current;
theSize++;
return { p->prev = p->prev->next = new Node{ x, p->prev, p } };
}
//Insert x before itr
iterator insert( iterator itr, Object && x )
{
Node *p = itr.current;
theSize++;
return { p->prev = p->prev->next = new Node{ std::move( x ), p->prev, p } };
}
//Erase item at itr
iterator erase( iterator itr )
{
Node *p = itr.current;
iterator retVal{ p->next };
p->prev->next = p->next;
p->next->prev = p->prev;
delete p;
theSize--;
return retVal;
}
iterator erase( iterator from, iterator to )
{
for( iterator itr = from; itr != to; )
itr.erase( itr );
return to;
}
iterator find( const Object & x )
{
iterator start= begin();
while(start!=end()){
if(x==*start)
return start;
start++;
}
return start;
}
/*
iterator find( string & x )
{
iterator start = begin();
while( start != end( ) ) {
if( strcasecmp( x.c_str( ),( *start ).getWord( ).c_str( ) )==0 )
return start;
else
start++;
}
return start;
}
*/
const_iterator find(const Object & x) const
{
const_iterator start=begin();
while(start!=end()){
if(x==*start)
return start;
start++;
}
return start;
}
/*
const_iterator find(const string & x){
const_iterator start = const_iterator(head);
while( start != end()){
if(strcasecmp(x.c_str(),(*start).getWord().c_str())==0)
return start;
else
start++;
}
return start;
}
*/
private:
int theSize;
Node *head;
Node *tail;
void init( )
{
theSize = 0;
head = new Node;
tail = new Node;
head->next = tail;
tail->prev = head;
}
};
#endif
HashTable.h:
#ifndef HASHTABLE_H
#define HASHTABLE_H
#include <vector>
#include <string>
#include "List.h"
#include "DictionaryEntry.h"
using namespace std;
//checks if a value is prime
bool isPrime(int n){
if( n==2 || n==3)
return true;
if( n==1 || n%2 == 0)
return false;
for(int i=3; i*i<n; i+=2)
if(n%i == 0)
return false;
return true;
}
//finds the next prime number
int nextPrime (int n) {
if( n%2==0)
n++;
while( !isPrime(n))
n+=2;
return n;
}
template <typename HashedObj>
class HashTable
{
public:
//constructor (explicit so no implicit conversion)
explicit HashTable( int size = 3500) : tableSize(size), currentSize(size), theLists(size) { }
//empty the Hashtable
void makeEmpty( )
{
currentSize=0;
//clear each linked list from hastable
for(int i=0; i<tableSize; i++)
theLists[i].clear( );
}
//search for x in Hashtable
bool contains( const HashedObj & x ) const{
//assign reference variable to rename the complicated object
const List<HashedObj> & whichList = theLists[ myhash( x ) ];
//return whether x already exists in the list
return whichList.find( x ) != whichList.end( );
}
//insert x into Hashtable (true if successful, false if already exists)
bool insert( const HashedObj & x ) {
//assign reference variable to rename the complicated object
List<HashedObj> & whichList = theLists[ myhash( x ) ];
//if x already exists in the list, return false
if( whichList.find( x ) != whichList.end() )
return false;
//otherwise push to list
whichList.push_front( x );
//rehash if new size is greater than hashtable size
if( ++currentSize >tableSize ) {
rehash( );
}
return true;
}
//remove x from Hashtable (true if successful, false if not found)
bool remove( const HashedObj & x ) {
//assign reference variable to rename the complicated object
List<HashedObj> & whichList = theLists[ myhash( x ) ];
//iterator is at end of list (i.e., not found)
if( whichList.find(x) == whichList.end() )
return false;
//erase x
whichList.erase( whichList.find (x) );
--currentSize;
return true;
}
HashedObj & retrieve( HashedObj & obj)
{
return *(theLists[myhash(obj)].find(obj));
}
private:
//The vector of linked-lists hashtable
vector<List<HashedObj> > theLists;
int currentSize;
int tableSize;
//Because coming with new stuff is hard <--Haha
void rehash( ){
vector<List<HashedObj> > oldLists=theLists;
int oldtableSize = tableSize;
tableSize = nextPrime( 2* oldtableSize );
//Create new double-sized, empty table
theLists.resize( tableSize );
for( int i=0; i<tableSize; i++ )
theLists[i].clear();
//copy table over
currentSize = 0;
for( int i=0; i<oldtableSize; i++ ){
while( !oldLists[i].empty() ){
insert( oldLists[i].front() );
oldLists[i].pop_front();
}
}
}
//call hash function and makes sure values fit in table
int myhash( const HashedObj & x ) const
{
int hashVal = hash2(x); //call hash function
//make sure the hash values fit into HashTable
hashVal %= tableSize;
if( hashVal < 0 )
{
hashVal += tableSize;
}
return hashVal;
}
/*
int myhash( const string & x ) const
{
int hashVal = hash( x );
hashVal %= tableSize;
if( hashVal < 0 )
{
hashVal += tableSize;
}
return hashVal;
}
*/
};
int hash2( const string & key )
{
int hashVal = 0;
for( int i = 0; i < key.length( ); i++ )
{
hashVal = 37 * hashVal + key[i];
}
return hashVal;
}
int hash2( const DictionaryEntry word )
{
return hash2(word.getEntry());
}
int hash2(int key)
{
return key;
}
#endif
DictionaryEntry.h:
#ifndef DICTIONARYENTRY_H
#define DICTIONARYENTRY_H
#include <string>
#include <iostream>
#include "HashTable.h"
using namespace std;
class DictionaryEntry
{
public:
DictionaryEntry( )
{
entry = "";
translation = "";
}
DictionaryEntry( const DictionaryEntry & rhs )
{
entry = rhs.entry;
translation = rhs.translation;
}
void set( string ent, string trans )
{
entry = ent;
translation = trans;
}
const string & getTranslation( ) const
{
return translation;
}
const string & getEntry( ) const
{
return entry;
}
bool operator== ( const DictionaryEntry & rhs ) const
{
return getEntry( ) == rhs.getEntry( );
}
bool operator!= ( const DictionaryEntry & rhs ) const
{
return (getEntry() != rhs.getEntry() );
}
private:
string entry;
string translation;
};
#endif
和Dictionary.py:
#!/usr/bin/python
from Tkinter import *
import subprocess
# general function for frame generation
def frame(root, side):
w = Frame(root)
w.pack(side=side, expand=YES, fill=BOTH)
return w
# general function for button generation
def button(root, side, text, command=None):
w = Button(root, text=text, command=command)
w.pack(side=side, expand=YES, fill=BOTH)
return w
# main class for GUI
class Translator(Frame):
def __init__(self):
Frame.__init__(self)
self.pack(expand=YES, fill=BOTH)
self.master.title("English-French Translator")
self.master.iconname("English-French Translator")
Label(self, text='English').pack(side=TOP, expand=YES, fill=BOTH)
english = StringVar()
Entry(self, relief=SUNKEN, textvariable=english).pack(side=TOP, expand=YES, fill=BOTH)
buttonsF = frame(self, TOP)
btn = button(buttonsF, LEFT, 'Translate')
btn.bind('<ButtonRelease-1>',
lambda e, s=self: s.translate(english, french))
clearF = frame(self, TOP)
btn = button(buttonsF, LEFT, 'Clear')
btn.bind('<ButtonRelease-1>',
lambda e, s=self: s.clearall(english, french))
randF = frame(self, TOP)
btn = button(buttonsF, LEFT, 'Flash Me (TM)')
btn.bind('<ButtonRelease-1>',
lambda e, s=self: s.random(english, french))
Label(self, text='French').pack(side=TOP, expand=YES, fill=BOTH)
french = StringVar()
Message(self, relief=SUNKEN, textvariable=french, width=200).pack(side=TOP, expand=YES, fill=BOTH)
# clear all text boxes
def clearall(self, english, french):
english.set('')
french.set('')
# translate english to french
def translate(self, english, french):
if (len(english.get()) > 0):
try:
# send english word to subprocess
process.stdin.write('%sn'%english.get())
# read line of output from subprocess (original text)
original=process.stdout.readline()
# read line of output from subprocess (translated text)
translation=process.stdout.readline()
# set english textbox
english.set(original.rstrip())
# set french textbox
french.set(translation.rstrip())
except:
clearall(english, french)
def random(self, english, french):
try:
process.stdin.write('randomn')
original=process.stdout.readline()
translation=process.stdout.readline()
english.set(original.rstrip())
french.set(translation.rstrip())
except:
clearall(english, french)
if __name__ == '__main__':
args='French.txt'
process=subprocess.Popen('Dictionary %s'%args, shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
Translator().mainloop()
错误消息会告诉您到底出了什么问题:"全局名称'clearall'未定义"。你必须问问自己,"为什么python认为它没有定义?"?"在这种情况下,线索是它认为clearall
是一个全局函数。为什么?因为你就是这样使用它的。
在查看您的代码时,您似乎有一个"clearall"方法作为对象的一部分,所以您所需要做的很可能就是在您调用clearall
的任何地方将clearall(...)
更改为self.clearall(...)
。