I'm making an expense tracker. I've created an Account class, that registers a specific budget. All the accounts are saved in a Budgets list. Then I try to save the Budgets list into a json file using the save function, which returns an error. This is kinda obvious, but I can't think of any efficient alternative. Any solution? PD: I deleted all the structure not related with the problem, because it already works, and it doesn't let me send all the code. Sorry if something seems out of context.
def initialize(filename):
"""
Adjusts the starting parameters.
"""
budgets = []
try:
# Checks if the file exists, and executes the apropiate code
# according to the situation.
with open(filename, 'r') as f_obj:
budgets = json.load(f_obj)
# Loads the info from older sessions
# into the list.
except FileNotFoundError: #If the file doesn't exist, we create it.
print("Seems you are the first one here!")
return budgets
class Account:
"""
Simulates a budget with custom percentatges for each area of spending
"""
def __init__(self, name, cash, percent):
self.name = name
self.cash = int(cash)
self.percent = percent
self.budget = {}
for key, value in self.percent.items():
self.budget[key] = self.cash * value / 100
def save(filename, budgets):
"""Saves the changes made into the accounts"""
with open(filename, 'w') as f_obj:
json.dump(budgets, f_obj)
def main():
"""Executes the main program"""
filename = "budgets.json"
budgets = initialize(filename)
while True:
a = input("\nSelect the desired operation (h for help): ")
if a == 'help':
help()
elif a == 'save':
save(filename, budgets)
print('account saved succesfully')
elif a == 'exit':
break
else:
print("ERROR: The input is not an operation\n")
I am really not sure about my solution, but!!! If I remember correctly, you
can only serialize dictionaries in json, so maybe try this out:
def save(filename, budgets):
"""Saves the changes made into the accounts"""
with open(filename, 'w') as f_obj:
budgets2 = [budget.__dict__ for budget in budgets]
json.dump(budgets2, f_obj)
Related
I am currently working on an inventory system that I have mocked up so far.
This is the following code:
import csv
class start_store:
def __init__(self):
self.name = self.ask()
self.options = self.ask_options()
def ask(self):
while 1:
name = input("What is your name?\n")
if name == "":
print("Ha! You have to enter a name!")
else:
print("Welcome to the Shepherdstown Bake Shop " + name)
return name
def ask_options(self):
while 1:
option = input('''What would you like to do? \n1. Add a Item: \n2. Delete a Item:\n3. Edit an Item: \n4. View Inventory \n5. End Program\n''')
if option == "4":
print("Here is the following inventory we have " + self.name)
items = CsvReader()
items.make_dict_items()
items.show_available()
break
else:
print("You have to enter a valid option " + self.name)
and the second class:
class CsvReader:
def __init__(self):
self.result = []
def make_dict_items(self):
with open("Items2.csv") as fp:
reader = csv.reader(fp)
labels = next(reader, None)
result = []
for row in reader:
row[0] = int(row[0])
row[1] = float(row[1])
row[2] = int(row[2])
pairs = zip(labels, row)
self.result.append(dict(pairs))
def show_available(self):
for item in self.result:
print(item)
obj = start_store() # create the instance
while 1:
obj.ask_options() # use the instance
From what I understand, I am able to run my code in IDLE based upon the last three lines in my second class, which initialize, and run. The program runs from : asking the user their name -> asking the user what they would like to do -> performing said task-> looping back to ask what to do.
I am confused on how I would implement a main method that runs my current program in that order? I understand how to make a main method, it being if __name__ == '__main__': , but what would I put under it? Would I have it run ask() like in the bottom of my lines? How do I add a main method that runs my program in this order in the sense that it is able to run now in IDLE without a main method?
I apologize if I am overlooking something, I am fairly new to Python and OOP.
Create 3 files: one file called csv_reader.py, one file called start_store.py, and a third called main.py. Place your CsvReader and start_store classes in the appropriate files, and in main.py write this:
from start_store import start_store
from csv_reader import CsvReader
if __name__ == "__main__" :
obj = start_store() # create the instance
while 1:
obj.ask_options() # use the instance
In your csv_reader.py file you should remove the code which creates an obj and the while loop - this should only be in the main.py file! This new file will include both of your classes (start_store and CsvReader) and run your main loop. You can run this with python main.py. It is worth noting that the file does not need to be called main.py (it can be called anything), and both classes could be included in the same file as the __main__ function, but this is just a simple example of how to separate your classes and then run them in a main loop.
With python whether you should have multiple classes in a file is a matter of opinion rather than a rule. If the classes are small then why not.
So all you need to do is put your if name == 'main': ahead of obj = start_store() ...
If the script is run from the command line to be able to cancel with Ctrl+C I like to use ...
def main()
obj = start_store() etc ...
return 0
if __name__ == "__main__":
try: # handle Ctrl+C
sys.exit(main())
except KeyboardInterrupt:
sys.exit(0)
I have a problem trying to access a variable from file a.py from a function in file b.py. I tried looking around the internet and could not find anything, or I don't know exactly how to look for what I need. I also tried to make another file and update the variable in file c.py, but file b.py still see's the first initialization of the variable. I tried to update the variable in file a.py and afterwards import a.py in the function in b.py.
File a.py
var = []
def run():
a.welcome()
while True:
menu = a.menu()
if menu == 1:
def retrieve_path(source_path):
"""The function takes 1 parameter and checks if the file name exist as well as the file path
Adds the csv data to a variable
source_path (str): Path against whom to check for validity
"""
if not source_path:
print("Invalid file name, Please try again\n")
return
else:
import os
isFile = os.path.isfile(source_path)
if not isFile:
print("Invalid file path\n")
return
else:
with open(source_path, "r") as csv_file:
csv_reader = csv.reader(csv_file, delimiter=',')
for line in csv_reader:
line = list(line)
var.append(line)
if __name__ == "__main__":
run()
file b.py
I tried like this but I get the first initialization of the variable var = []
I first updated var from file a.py and afterwards, I tried to use the function below inside file b.py but still the same result.
from a import var
from a import *
import a
def a_function():
from a import var
from a import *
import a
print(var)
print(a.var)
This prints the first initialization of var which = [] not after it was appended.
If I print var from a, from inside the function it prints it updated.
If I print var from a, from outside the function it prints it updated.
What I don’t understand is, why after updating it, and importing it into b, I still get the first initialization. Debugger didn’t help as well.
I can work around it by adding the function retrieve_path inside b.py and then appending the data in another variable inside file b.py but I would like to know why its not importing var updated with the data.
File b.py
var2 = []
def retrieve_path(source_path):
"""The function takes 1 parameter and checks if the file name exist as well as the file path
Adds the csv data to a variable
source_path (str): Path against whom to check for validity
"""
if not source_path:
print("Invalid file name, Please try again\n")
return
else:
import os
isFile = os.path.isfile(source_path)
if not isFile:
print("Invalid file path\n")
return
else:
with open(source_path, "r") as csv_file:
csv_reader = csv.reader(csv_file, delimiter=',')
for line in csv_reader:
line = list(line)
var.append(line)
var2.append(line)
The reason I didn't use Class if that was one of the solutions, is because I haven't learned that much about Classes and don't know how to use them properly for the time being.
I hope I was quite explicit and you understand my dilemma. Also, have in mind I just started learning Python, so a newbi explanation and solution are more than welcomed.
The correct way is to call the run function before accessing var. Either
import a
a.run
print(a.var)
or:
from a import var, run
run
print(var)
The import statement only runs the content of the module, not the functions declared in it.
The idiomatic way of running a script is indeed what you have in a.py:
if __name__ == "__main__":
run()
And the run function will be called if you use the file like a script with python a.py, because a file that is started directly by the interpretor will be named __main__. But when it is imported, it is named according to the file name. So here it would be a and not main. Said differently, run is never called when a.py is imported.
One possibility would be to end a.py with an unconditional call of run:
...
line = list(line)
var.append(line)
run()
It should be harmless because Python keeps track of the already imported module, and run should be called only once even if the module was imported from multiple places. Yet it would be an anti-pattern, because by convention import should have as few side effects as possible, while run seems to do plenty of actions.
Ok, this is just a part of the project which was for the school, which I finished, but I wanted to make this part with records a little bit different than I've done for the grade. If some function dont make sense, its because the project it is not finished. My only concerned is towards records variable.
main.py
import tui, csv
records = []
def run():
tui.welcome()
while True:
menu = tui.menu()
if menu == 1:
def retrieve_path(source_path):
"""The function takes 1 parameter and checks if the file name exist as well as the file path
Adds the csv data to a variable
source_path (str): Path against whom to check for validity
"""
if not source_path:
print("Invalid file name, Please try again\n")
return
else:
import os
isFile = os.path.isfile(source_path)
if not isFile:
print("Invalid file path\n")
return
else:
with open(source_path, "r") as csv_file:
csv_reader = csv.reader(csv_file, delimiter=',')
for line in csv_reader:
line = list(line)
records.append(line)
tui.started("Data Loading")
retrieve_path(tui.source_data_path())
tui.completed("Data Loading")
if menu == 2:
tui.started("Retrieving data")
process_menu = tui.process_type()
tui.completed("Retrieving data")
if process_menu == 1:
tui.started("Retrieving entity name")
tui.entity_name()
tui.completed("Retrieving entity name")
if process_menu == 2:
tui.started("Retrieving entity details")
entity, cols = tui.entity_details()
tui.list_entity(entity, cols)
tui.completed("Retrieving entity details")
if menu == 3:
print(tui.main_records)
if menu == 4:
break
if __name__ == "__main__":
run()
Second file is:
tui.py
def welcome():
message = "System Management"
print("*" * len(message))
print(message)
print("*" * len(message))
def menu():
main_menu = "-"
while main_menu != "0":
if main_menu == "-":
print('Main Menu:'
'\n1. Load Data'
'\n2. Process Data'
'\n3. Visualise Data'
'\n4. Save Data'
'\n0. Exit')
elif main_menu in "1234":
return int(main_menu)
elif main_menu not in "1234":
error(main_menu)
return None
else:
print('Main Menu:'
'\n1. Load Data'
'\n2. Process Data'
'\n3. Visualise Data'
'\n4. Save Data'
'\n0. Exit')
main_menu = input()
def started(operation):
print("{} has started.\n".format(operation))
def completed(operation):
print("{} has completed.\n".format(operation))
def error(error_msg):
print("Error! {} is not a valid option.".format(error_msg))
def source_data_path():
print("Please enter the path to the source data file:")
source_path = input()
if ".csv" not in source_path:
return None
else:
return source_path
def process_type():
process_menu = "-"
while process_menu != "0":
if process_menu == "-":
print('Process Menu:'
'\n1. Retrieve entity'
'\n2. Retrieve entity details'
'\n3. Categorise entities by type'
'\n4. Categorise entities by gravity'
'\n5. Summarise entities by orbit'
'\n6. Return to Main Menu')
elif process_menu == "6":
menu()
return None
elif process_menu in "12345":
return int(process_menu)
elif process_menu not in "12345":
error(process_menu)
return None
else:
print('Process Menu:'
'\n1. Retrieve entity'
'\n2. Retrieve entity details'
'\n3. Categorise entities by type'
'\n4. Categorise entities by gravity'
'\n5. Summarise entities by orbit'
'\n6. Return to Main Menu')
process_menu = input()
def entity_name():
entity = input("Please enter the name of an entity: ")
return entity
def entity_details():
entity = input("Please enter the name of an entity: ")
indexes = input("Please enter the indexes number (e.g. 0,1,5,7):\n")
return entity, list(indexes)
Please have
First time I did the project I added def retrieve_path(source_path): to tui.py and it worked fine.
What I don't really understand is why is the variable records being appended to, I can print it from within run and outside of run function, but in tui.py i get only records = [] and how to solve this without creating the function retrieve_path in tui.py
This is what it was asked of us at the time being and it was not my personal choice to do it like this.
I am sorry for not pasting everything here and mistyping some parts like == _ main _ .
I have a book library program that it's class reads a file containing ID and name and assign them to self objects as id and card holder. then there is self object for borrowed books, so then I can identify which user borrowed which book.
The problem is in main function when a user return a book, I don't know how to update the self borrowed book object to delete that book from the object, so the self id will not have books borrowed to it.
Here is how the class looks:
#loan time length is 3 weeks by default
LOAN_TIME = 3
class Librarycard:
def __init__(self, card_id, card_holder):
self.__id = card_id
self.__holder = card_holder
#a dictionary that will contain the full book : loan time, updated in later function
self.__loan = {}
def return_book(self, book):
del self.__loan[book]
print('returned')
return
and this is my main function part which concern the book loaning:
def main():
command = input("Command: ")
#borrowed books main list to check if book borrowed or not
borrowed_books = []
if command == "R":
book = input("Book code: ")
if book not in borrowed_books:
print('This book has not been borrowed by anyone')
else:
del borrowed_books[book]
print('book returned')
# this is where I try to enter the function from the class to update the object
# dictionary
book.return_book(book)
if __name__ == "__main__":
main()
A couple of issues here.
First, the book that comes from the input is a string and not the actual book class. So, when calling book.return_book(book), the compiler is looking for a method return_book in the string class (which is obviously not there).
Second, borrowed_books is never being updated in the main class, so the user will never return any books.
Third, instead of using del in the Class, use self.__loan.pop(book). It is the inbuilt python function, and is a better way to remove the book.
Finally, there are a lot of camel case issues
Here is what the final code may look like.
class LibraryCard:
def __int__ (self, card_id, card_holder):
self.card_id=card_id
self.__card_holder=card_holder
self.checked_out={}
def return_book (self, book_id):
popped = self.checked_out.pop(book_id, "Book was already returned, or was never checked out")
if (popped != "Book was already returned, or was never checked out"):
print("Book returned: "+popped)
else:
print(popped)
def isCard(self, id, name):
return self.card_id==id and self.__card_holder==name
def main():
cards = {}
while (true):
command = input("To check out a book press \"C\", to return a book press \"R\" (without the quotes):\t")
print("Whether or not you have an account, please follow the instructions below")
card_id=input("Enter your card id:\t")
user_name=input("For security purposes, enter your name:\t")
if (user_id not in cards):
print("Welcome to Library Services")
cards[user_id] = LibraryCard(card_id, user_name)
if (not cards[user_id].isCard(user_id, user_name)):
print("Wrong user name or user id, please retry")
continue
if (command=="C"):
book=input("Enter the name of the book you would like to check out: ")
cards[user_id].checked_out[book]=3
print("Checked out successfully!")
else:
book=input("Enter the name of the book you would like to return: ")
cards[user_id].return_book(book)
class Librarycard:
def __init__(self, card_id, card_holder):
self.__id = card_id
self.__holder = card_holder
# a dictionary that will contain the full book : loan time, updated in later function
self.__loan = {'tttt': {},"uuuu":{}}
def return_book(self, book):
del self.__loan[book]
print('returned')
return
def main():
# command = input("Command: ")
command = "R"
# borrowed books main list to check if book borrowed or not
borrowed_books = ["tttt","aaaa"]
if command == "R":
# book = input("Book code: ")
book = "tttt"
if book not in borrowed_books:
print('This book has not been borrowed by anyone')
else:
borrowed_books.remove(book)
print('book returned')
library_book = Librarycard('card_id', 'you know holder')
print("before ",library_book._Librarycard__loan)
library_book.return_book(book)
print("after ",library_book._Librarycard__loan)
if __name__ == "__main__":
main()
C:\Users\sharp\AppData\Local\Programs\Python\Python39\python.exe C:/Users/sharp/Desktop/project/testid.py
book returned
before {'tttt': {}, 'uuuu': {}}
returned
after {'uuuu': {}}
Process finished with exit code 0
I have fixed it in a way that I added a new variable that connects the class in the main function, then did a loop that runs into all the cards inside the class keys of the class, and finally with that key I activated the return book function.
The main issue was that I didn't create an access for which ID I wanted to delete the book from. but once activated with the for loop I was able to reach all ID'S object and delete the book from the one that has it.
Here is how the code looks like in the specific parts concerning this problem:
def main():
#function that reads the text file and assign the card ids and card holders as a
#dictionary.
library = read_card_data("library.txt")
while True:
command = input("Command: ")
if command == "R":
book = input("Book code: ")
if book not in borrowed_books:
print('This book has not been borrowed by anyone')
else:
del borrowed_books[book]
for card in library.keys():
library[card].return_book(book)
I've written a program and want to call the functions in the main. However, I've been receiving a SyntaxError. I'm not sure what I'm doing wrong. Here is my code, I've tried a few things but the main function won't call the rest of the functions.
class Matrix(object):
def open_file():
'''Opens the file if it exists, otherwise prints out error message'''
Done = False
while not Done:
try:
File = input("Enter a filename: ").lower() #Asks user for a file to input
Open_File = open(File, "r") #Open the file if it exists and reads it
Info = Open_File.readlines()[1:]
Open_File.close() #Close the file
Done = True #Exits the while loop
except FileNotFoundError:
print("Sorry that file doesn't exist!") #prints out error message if file doesn't exist
return Info #Info is the file_pointer(fp)
def __init__(self): # This completed method is given
'''Create and initialize your class attributes.'''
self._matrix = {} #Intialize the matrix
self._rooms = 0 #Set the rooms equal to zero
def read_file(self, Info): #Info is equvalient to the file pointer or fp
'''Build an adjacency matrix that you read from a file fp.'''
self._rooms = Info.readline()
self._rooms = int(self._rooms)
for line in Info:
a, b = map(int, line.split())
self._matrix.setdefault(a, set()).add(b)
self._matrix.setdefault(b, set()).add(a)
return self._rooms and self._matrix
def __str__(self):
'''Return the adjacency matrix as a string.'''
s = str(self._matrix)
return s #__str__ always returns a string
def main(self):
matrix = Matrix()
info = matrix.open_file()
matrix.read_file(info)
s = str(matrix)
print(s)
if __name__ == '__main__':
m = Matrix()
m.main()
A few things:
it's self.read_file, not just read_file. It's an instance method so you need to use self.
Same for __init__(self), you need to call self.__init__. Although typically you don't do this manually. You would "instantiate" the class via Matrix().
You can't assign to a function call, so open_file() = Info simply doesn't make sense. Perhaps you mean info = open_file().
It looks like you're a little confused about how to lay out your class. Try leaving main outside of the class, like this (untested):
def main:
matrix = Matrix()
info = matrix.open_file()
matrix.read_file(info)
s = str(matrix)
print(s)
You will also need to dedent if __name__ == '__main__' to the global scope.
Ideally you may want to write something like below. Also, your open_file() has to be rewritten.
class Matrix(object):
def open_file(self):
File = input("Enter a filename: ").lower() #Asks user for a file to input
fp = open(File, "r")
return fp
#### Your matrix class code goes here
def main():
myMatrix = Matrix()
fp = myMatrix.open_file()
ret = myMatrix.read_file(fp)
print(myMatrix)
if __name__ == "__main__":
main()
There is an error in your program's entry. ' if name == 'main':'shouldn't be included in a Class. It should be global. And another, you want to call a member function of Matrix, but where is the object of Matrix. The code below is correct:
Class Matrix(object):
#################
your codes
#################
if __name__ == '__main__':
m = Matrix()
m.main()
the way this is posted
if __name__ == "__main__":
main()
is going to be executed when the class is defined -- not when the program is run. As written, the class won't have been instantiated so there's no Matrix object on which you can call main().
You'll need to move the call out one indent, so it is aligned with the class definition, and then create an object before calling its main():
if __name__ == "__main__":
instance = Matrix()
instance.main()
You've also got the assignments backwards in main(). It should read more like this:
info = open_file()
self.read_file(Info)
s = __str__(self)
print(s)
the open_file() method also has some issues. You want to create Info outside the scope of your loop so you know you've got it to return. Your comment indicates the Info is supposed to be the file pointer -- but it's not, as you wrote it. Open_File is the file pointer, and Info is the content of the file (at least, everything but the first line). Unless you're expecting a huge amount of data, it's probably easier to pass the contents -- or to combine open_file and read_file into the same function.
You also want to use the usual python pattern for opening and closing the files the with context manager - that will close your file for you.
Heres a quick and dirty version of Open_file and Read_file in one package.
def read_file(self):
#get the filename first
filename = None
while not filename:
user_fn = input("Enter a filename: ").lower()
if os.path.exists(user_fn):
filename = user_fn
else:
print ("Sorry that file doesn't exist!")
# 'with' will automatically close the file for you
with open(filename, 'rt') as filepointer:
# file objects are iterable:
for line in filepointer:
a, b = map(int, line.split())
self._matrix.setdefault(a, set()).add(b)
self._matrix.setdefault(b, set()).add(a)
I'm not clear what self._matrix.setdefault(a, set()).add(b) is supposed to be doing for you here, but in syntactic terms you can simply the structure to "get the filename, open with with, iterate over it"
I'm trying to keep this as simple as possible. Basically I want the data to be saved to a file, and the retrieve it so that questor.py works and can "remember" everything it was ever taught on your machine. The original code is available on the web at http://www.strout.net/info/coding/python/questor.py
If I'm reading the code right, you end up with an object that looks something like {key:{key:{key:class instance},class instance},class instance} . (rough estimate)
Please ignore the unfished method Save, I'm working on that as soon as I figure out how to pickle the dictionary without losing any of the imbedded instances.
The following is my attempt at trying to save the dict via pickler. Some of the code is unfinished, but you should be able to get an idea of what I was trying to do. So far all I am able to do is retrieve the last question/answer set. Either my pickle isn't saving the imbedded instances, or they're not actually there when I save the pickle. I've followed the spaghetti lines as much as possible, but can't seem to figure out how to set up a way to save to file without losing anything.
Also my file doesn't have to be .txt originally I was going to use .data for the pickle.
# questor.py
# define some constants for future use
kQuestion = 'question'
kGuess = 'guess'
questfile = 'questfile.txt'
## Added
import cPickle as p
# create a file for questor
def questor_file():
try:
questor = open(questfile,'rb')
try:
q = p.Unpickler(questor)
quest = q.load()
questor.close()
return quest
except:
print 'P.load failed'
except:
print 'File did not open'
questor = open('questfile.data', 'wb')
questor.close()
return Qnode('python')
# define a function for asking yes/no questions
def yesno(prompt):
ans = raw_input(prompt)
return (ans[0]=='y' or ans[0]=='Y')
# define a node in the question tree (either question or guess)
class Qnode:
# initialization method
def __init__(self,guess):
self.nodetype = kGuess
self.desc = guess
##Added
## Not sure where I found this, but was going to attempt to use this as a retreival method
## haven't gotten this to work yet
def Load(self):
f = open(self.questfile,'rb')
tmp_dict = cPickle.load(f)
f.close()
self.__dict__.update(tmp_dict)
##Added
# was going to use this as a save method, and call it each time I added a new question/answer
def Save(self,node):
f = open(self.questfile,'wb')
quest = p.pickler(f)
# get the question to ask
def query(self):
if (self.nodetype == kQuestion):
return self.desc + " "
elif (self.nodetype == kGuess):
return "Is it a " + self.desc + "? "
else:
return "Error: invalid node type!"
# return new node, given a boolean response
def nextnode(self,answer):
return self.nodes[answer]
# turn a guess node into a question node and add new item
# give a question, the new item, and the answer for that item
def makeQuest( self, question, newitem, newanswer ):
# create new nodes for the new answer and old answer
newAnsNode = (Qnode(newitem))
oldAnsNode = (Qnode(self.desc))
# turn this node into a question node
self.nodetype = kQuestion
self.desc = question
# assign the yes and no nodes appropriately
self.nodes = {newanswer:newAnsNode, not newanswer:oldAnsNode}
self.save(self.nodes)
def traverse(fromNode):
# ask the question
yes = yesno( fromNode.query() )
# if this is a guess node, then did we get it right?
if (fromNode.nodetype == kGuess):
if (yes):
print "I'm a genius!!!"
return
# if we didn't get it right, return the node
return fromNode
# if it's a question node, then ask another question
return traverse( fromNode.nextnode(yes) )
def run():
# start with a single guess node
# This was supposed to assign the data from the file
topNode = questor_file()
done = 0
while not done:
# ask questions till we get to the end
result = traverse( topNode )
# if result is a node, we need to add a question
if (result):
item = raw_input("OK, what were you thinking of? ")
print "Enter a question that distinguishes a",
print item, "from a", result.desc + ":"
q = raw_input()
ans = yesno("What is the answer for " + item + "? ")
result.makeQuest( q, item, ans )
print "Got it."
# repeat until done
print
done = not yesno("Do another? ")
# Added
# give me the dictionary
return result
# immediate-mode commands, for drag-and-drop or execfile() execution
if __name__ == '__main__':
print "Let's play a game."
print 'Think of something, just one thing.'
print 'It can be anything, and I will try to guess what it is.'
raw_input('Press Enter when ready.')
print
questdata = run()
print
# Added
# Save the dictionary
questor = open(questfile,'wb')
q = p.Pickler(questor)
q.dump(questdata)
questor.close()
raw_input("press Return>")
else:
print "Module questor imported."
print "To run, type: questor.run()"
print "To reload after changes to the source, type: reload(questor)"
# end of questor.py
one way that comes to mind is creating a list of all the nodes and saving that ... they should keep their internal pointers on their own.
declare a list of nodes at the top of your file (and use pickle... just cause Im more familiar with that)
import pickle
kQuestion = 'question'
kGuess = 'guess'
questfile = 'questfile.txt'
nodes = []
....
change your load method to something like
def questor_file():
global nodes
try:
questor = open(questfile,'rb')
try:
nodes= pickle.load(questor)
quest = nodes[0]
questor.close()
return quest
except:
print 'P.load failed'
nodes = []
except:
print 'File did not open'
nodes = []
return Qnode('python')
change your class constructor so that it adds each node to nodes
class Qnode:
# initialization method
def __init__(self,guess):
self.nodetype = kGuess
self.desc = guess
nodes.append(self)
at the end where it says #added save dictionary , save your list of nodes
questor = open(questfile,'wb')
q = pickle.dump(nodes,questor)
make sure you exit the program by typing no when prompted ...
you could also save it to a database or whatever but you would still have to store each node and it might be more complicated... this method should really be fine I think , (although there may be a more natural way to save a tree structure) ...