Why does my main program default to the except? - python

Could you possibly check my syntax and tell me why the debugger skips my try statement and skips to the except.
book class:
class book(object):
def _init_(self, title, author, numPages):
if title is None:
raise ValueError("invalid 'title' argument. please try again")
if author is None:
raise ValueError("invalid 'author' argument. please try again")
if numPages <= 0:
raise ValueError("invalid 'numPages' argument. please try again")
self.title = title
self.author = author
self.numPages = numPages
main class:
from book import book
def printBook (b):
if b is None:
raise ValueError('invalid book argument')
print (b.author + ": " + b.title + "\n" +" Number of page: " + b.numPages )
if __name__ == '__main__':
try:
b1 = book("The Eye of the World", "Robert Jordan", 685)
b2 = book("The Heir of Novron", "Michael J. Sullivan", 932)
printBook(b1)
printBook(b2)
except:
print("ERROR: INVALID BOOK")

There are at least 2 mistakes:
Constructor is called __init__ as jonsharpe already mentioned
you need str() for concatenation of ints and string. So you need to modify your print function:
print (b.author + ": " + b.title + "\n" +" Number of page: " + str(b.numPages) )

Related

How can I prevent my JSON file from getting overwritten in Python?

I am currently building a school homework project - a contact manager, using classes in Python.
I was able to assemble all the needed parts to make my code work, yet upon exiting the program with Terminal, the data inside of my JSON file keep being overwritten.
I've tried changing the with open attribute to "w" and "a", sadly nothing works.
Main Code:
from colorama import Fore, Style
from LoadAndSave import load_file, save_file
from ContactBook import ContactBook
contacts = []
DATA_FILE = "contactbook.json"
def menu():
print(Fore.RED + "Welcome to Contacts Manager v2.0.0!" + Style.RESET_ALL)
print(Fore.LIGHTCYAN_EX + "Please enter your selection according to the menu." + Style.RESET_ALL)
print("a - Add a contact")
print("r - Remove a contact")
print("s - Search for a contact")
print("p - Print a list of all contacts")
print("x - Exit")
user_selection = input(Fore.GREEN + "Your selection: " + Style.RESET_ALL)
return user_selection
def main():
load_file(DATA_FILE)
contactbook = ContactBook()
user_selection = ""
while user_selection != "x":
user_selection = menu() # As long as user did not select "x", program will always run.
if user_selection == "a":
contactbook.add_contact(input("Please enter contact's name: "), int(input("Please enter contact's number: ")))
if user_selection == "r":
contactbook.remove_contact(contactbook.search_contact(input("Contact's Name? ")))
if user_selection == "s":
contactbook.search_contact(input("Contact's name?"))
print(Fore.GREEN + "Success!" + Style.RESET_ALL)
if user_selection == "p":
print(contactbook)
print(Fore.GREEN + "Success!" + Style.RESET_ALL)
print(Fore.MAGENTA + "Thank you for using my software. Bye!")
save_file(contactbook.make_contact_json(), DATA_FILE)
if __name__ == "__main__":
main()
Load and save:
import json
def load_file(DATA_FILE): # Loading JSON file with all information
with open (DATA_FILE) as file:
return json.load(file)
def save_file(json_list, DATA_FILE):
with open (DATA_FILE, "w") as file:
json.dump(json_list, file, indent = 4)
Contact & ContactBook classes:
import json
class Contact:
name = ""
tel = 0
def __init__(self, name = "", tel = 0):
self.name = name
self.tel = tel
def __str__(self):
return json.dumps({"contact_info":[{"name": self.name, "tel": self.tel}]})
from colorama import Fore, Style, Back
from Contact import Contact
import json
class ContactBook:
contacts = []
def __init__(self):
pass
def add_contact(self, name = "", tel = 0):
self.contacts.append(Contact(name, tel))
print(Fore.GREEN + "Success!" + Style.RESET_ALL)
def remove_contact(self, contact_name):
self.contacts.remove(contact_name)
print(Fore.RED + "Removed.\n" + Style.RESET_ALL)
def search_contact(self, contact_name):
for contact in self.contacts:
if type(contact) is Contact:
if contact.name == contact_name:
return contact
return (Back.RED + "\nThere is no contact with that name." + Style.RESET_ALL + "\n")
def make_contact_json(self):
result = []
for contact in self.contacts:
result.append(json.loads(contact.__str__()))
return result
def __str__(self) -> str:
result = ""
for contact in self.contacts:
result += contact.__str__()
return result
JSON File:
[
[
{
"name": "sdfgh",
"tel": 654321
}
]
]
Thanks in advance to all helpers!
Your contacts are getting overwritten because every time you run your program, you are creating a fresh ContactBook
contactbook = ContactBook() # In your Main Code
This in turn initializes an empty contacts list
contacts = [] # Inside Class ContactBook
I suggest that you add an __init__ logic to you ContactBook Class that initialises your contacts list with the existing ones
Something Like
class ContactBook:
def __init__(self, existing_contacts=None):
self.contacts = [] if existing_contacts is None else existing_contacts
Also while creating the ContactBook object in you main code please pass the existing contacts.
try:
existing_contacts = load_file(DATA_FILE)
except FileNotFoundError:
existing_contacts = None
contactbook = ContactBook(existing_contacts)
Also please make sure that you are saving the contacts correctly. It seems to currently be a list of list of objects where as it should ideally be a list of objects
Hope you get good grades. Peace out.

Python TypeError: CreateAccount() missing 1 required positional argument

I created this terminal app a while ago and it was working, but I haven't touched in a while and I just opened it back up and I can't figure out what this error is and why I'm having it. It's happening during the account creation part of my program. I tried a couple things out but I'm still not sure what's going on.
**TypeError: CreateAccount() missing 1 required positional argument**
main.py
from Account import Account
from Transaction import Transaction
from enum import Enum
from fcp import CreateAccount
#variables and lists needed for program
new_accounts = []
#do no tneed, just put the balance of 0 straight into the factory class attribute
#balance = 0
user_name = []
Transactions = []
account_number = 0
#***Functions for switch statements***
def create_user():
global new_accounts
global account_number
active_create_account = False
new_username = input("\n\nCreate a username:")
email = input("Write your email: ")
account_number +=1
print(account_number)
# append the createaccount call straight into new_accounts.append
new_accounts.append(CreateAccount(user_name,email, int(input('Choose 1 for Checkings or 2 for Savings: ')), 0, 0))
active_create_account = True
for i in new_accounts:
if account_number == i.account_number:
i.new_account_creation()
account_search_balance = True
if account_search_balance == False:
print("\nThat account does not exist. Please re-enter option 5 and try again.")
main()
fcp.py
from Account import Account
from Transaction import Transaction
#BLANK CLASS TEMPLATE
def CreateAccount(self,user_name,email,account_type,balance,account_number):
account_number +=1
if (account_type == 1): return CreateCheckingAccount(user_name,email,1,balance,account_number)
if (account_type == 2): return CreateSavingsAccount(user_name,email,2,balance,account_number)
else:
return CreatAccount(user_name,email, int(input('Choose 1 for Checkings or 2 for Savings: ')),balance,account_number)
def CreateCheckingAccount(self,user_name,email,account_type,balance,account_number):
return Account(user_name, email,'Checking',balance,account_number)
def CreateSavingsAccount(self,user_name,email,account_type,balance,account_number):
return Account(user_name, email,'Savings',balance,account_number)
transaction.py
import datetime
class Transaction():
def __init__(self,account_number,type_of_transaction,old_balance,new_balance,date = datetime.datetime.now()):
self.account_number = account_number
self.type_of_transaction = type_of_transaction
self.old_balance = old_balance
self.new_balance = new_balance
self.date = datetime.datetime.now()
def to_string(self):
print("\nThe account number is: " + str(self.account_number) + "\nThe type of transaction is: " + self.type_of_transaction + "\nThe old balance was: " + str(self.old_balance) + "\nThe new balance is: " + str(self.new_balance) + "\nThe date of the transaction was: " + str(self.date))
def print_date(self):
print(str(self.date))
Account.py
class Account(object):
def __init__(self,user_name,email,account_type,balance,account_number):
self.user_name = user_name
self.email = email
self.account_type = account_type
self.balance = balance
self.account_number = account_number
def print_balance(self):
print("\nAccount bala is "+ str(self.balance))
return
def new_balance(self):
print("\nThe new account balance is: " + str(self.balance))
def to_string(self):
print("\nUsername: " + self.user_name + "\n\nEmail: " + self.email + "\n\nAccount type: " + (self.account_type) +
"\n\nYour account balance is:" + str(self.balance) +"\n\nAccount number: " + (self.account_number))
def new_account_creation(self):
print("\nCongragulations on your new account! Below is the info:\nUsername: " + self.user_name + "\nEmail: " + self.email + "\nAccount type: " + self.account_type +
"\nYour account balance is:" + str(self.balance) +"\nAccount number: " + str(self.account_number)+ " <--- Do NOT forget this number")
def Deposit(self):
deposit = int(input("\nHow much would you like to deposit?: "))
self.balance += deposit
def withdraw(self,withdraw):
self.balance -= withdraw
you should initiate the class object that contains createAccount() method before invoke.
class TestClass:
def __init__(self):
print("in init")
def createAccount(self, ...):
print("in Test Func")
testInstance = TestClass()
testInstance.createAccount(...)
It looks as though your method definition requires self as an argument but CreateAccount is not in a class. Therefore it is not required.
(remove self in the required arguments)
It's pretty clear, even though you left out the rest of the error message and failed to minimize your code: your function profile requires a self argument that the call didn't bother to provide. Since you used the name self, it seems as if you might want to create a class -- but you didn't do that with the function, nor with the call.
If a class is, indeed, what you want, then please return to your tutorial on class to make sure you implement all of the right items.

String argument error with dictionary commands

I am trying to create a basic online store in python. But whenever I try to 'buy' an item it shows an error with my dictionary or something I am not sure.
The error: users[n]["Transactions"] = users[n]["Transactions"] + str(names_f, "bought", quanti, "of", final[choice*3], "with a total price of $"+price)
TypeError: str() takes at most 3 arguments (6 given)
coun = 0
users = [{"name":"Jack","username":"ja", "cc":'12345',"email":'whwhwwhh', "code": '111', "Transactions": ""}]
def sign_in():
username = input("Enter username")
for i in range (len(users)):
for x in users[i].values():
if x == username:
pin = input("Enter pin")
if pin == users[i].get("code"):
print("Welcome", users[i].get("name"))
menu(username,users[i].get("name"))
break
else:
print("Wrong pin")
sign_in()
def menu (usern, names_f):
global coun
if coun == 0:
order = ''
total = 0
for i in range (len(categories)):
print(str(i+1)+".", categories[i])
choice = int(input("Choose a category by typing the number beside the categories name."))-1
print("Items in this list are")
print("Itemname \t Price \t Stock")
final = location[choice]
for c in range((int(len(final)/3))):
print(str(c+1)+'.',str(final[c*3]),"\t",'$'+str(final[c*3+1])), "\t", str(final[(c*3)+2])
choice = int(input("Which item (Type number on left of the item name)"))-1
while True:
quanti = int(input("How many do you want to buy"))
if quanti > final[choice*3+2]:
print("Sorry your request for", quanti, "Is more than we have at the store please try again")
continue
else:
price = str(quanti*final[choice*3+1])
final[choice*3+2] = final[choice*3+2]-quanti
print("Thank you for your purchasing",quanti,"of", final[choice*3], "Your total price of this buy is", '$'+price)
for n in range (len(users)):
if usern == users[n].get("username"):
users[n]["Transactions"] = users[n]["Transactions"] + str(names_f, "bought", quanti, "of", final[choice*3], "with a total price of $"+price)
order += str(quanti, 'of', final[choice*3])
price += int(price)
done = input("Do you want to check out then type '1' if you want to continue type '2'")
if done == '1':
print("Thank you")
print ("Invoice:", order, "/n total price (HKD) $"+str(price))
else:
coun += 1
menu(usern,names_f)
variable_name = users[n]["Transactions"] + str(names_f) + "bought" + str(quanti) + "of" + str(final[choice*3]) + "with a total price of $"+ str(price)
users[n]["Transactions"] = variable_name
You will maybe need to declare variable_name somewhere.
Problem is that str usage is following
str(object, encoding=encoding, errors=errors)
but whenever you pass comma it count it as another parameter.
P.S. I'm not sure if you need all those str in my solution.
str is a class, and as stated in the docs you can pass up to 3 parameters to it:
class str(object=b'', encoding='utf-8', errors='strict')
Also, it also says what it does:
Return a string version of object. If object is not provided, returns the empty string.
Meaning it is used to cast other types to string. Thus, you need to convert every int individually:
users[n]["Transactions"] = users[n]["Transactions"] + str(names_f) + " bought " + str(quanti) + " of " + str(final[choice*3]) + " with a total price of " + str(price)
Note the spaces before and after every string. Alternatively, you can format your string:
users[n]["Transactions"] = users[n]["Transactions"] + '%s bought %s of %s with a total price of %s' % (names_f, quanti, final[choice*3], price)
As a side note, it's worth checking what happens when the first transaction is made. If the key Transactions does not yet exist, you need to add an initial value before accessing it.
I usually do it like:
if key not in dict_:
dict_[key] = 'my initial value'
dict_[key] += 'add my stuff'
another solution would be using the get method, which allows you to add a default value:
dict_.get(key, 'default')
Note that this will not add the key to the dictionary, meaning that trying to access its value later on will still result in a Key Error.

Python selectively writing specific statement

The below def is working perfectly in cmd, but when writing to the file, it is only writing the second data.write statement. The first statement is definitely working, it is just not writing. Given the code is identical i can't figure out for the life of me what is wrong.
def follower_count(list1):
for name in list1:
name = '#' + name
try:
user = api.get_user(name)
if user.followers_count < 5000:
print ""
print "FAILED TEST"
print name
print user.followers_count
data.write(name + ": " + user.followers_count + "\n")
else:
print ""
print name
print user.followers_count
except:
print ""
print "Error grabbing " + name
data.write("Error Grabbing: " + name + "\n")
return()
data.write(name + ": " + user.followers_count + "\n")
This line will crash with TypeError: Can't convert 'int' object to str implicitly if user.followers_count is an integer.
Try using str.format to interpolate your strings.
data.write("{}: {}\n".format(name, user.followers_count))
Furthermore, you're making debugging much harder for yourself by not displaying any diagnostic information in your except. You know that an error occurred, but don't know anything about that error specifically. At the very least, you could do:
except Exception as e:
print ""
print "Error grabbing " + name
data.write("Error Grabbing: " + name + "\n")
data.write(e.message + "\n")
Which will at least tell you what the error message is.

arcpy calculate string field: Any ideas what how to fix this?

Im trying to store a string value obtained from a loop through a tuple into a field called ROW_1
the code goes like this
for creekclass in listOfClassTuples:
(classname, Permanency, creekWidth, score) = creekclass
arcpy.AddMessage(int(score))
bufferDistance = creekWidth*0.5
if crossingType == "INTERSECT":
stringBuffer = ""
else:
stringBuffer = "%s Meters" % str(bufferDistance)
arcpy.AddMessage(str(bufferDistance))
arcpy.MakeFeatureLayer_management(sourceLayer,"JUST_SELECTED", fieldName +" = '"+ classname + "'")
#arcpy.SelectLayerByAttribute_management("JUST_SELECTED","NEW_SELECTION",fieldName+" = '"+ classname + "'")
#arcpy.SelectLayerByAttribute_management("JUST_SELECTED","SUBSET_SELECTION",fieldName2+" = '"+ Permanency + "'")
#arcpy.CopyFeatures_management("JUST_SELECTED", "A:\Temporary\TempLayer1.shp")
arcpy.SelectLayerByLocation_management(targetLayer, crossingType,
"JUST_SELECTED", stringBuffer, "NEW_SELECTION")
## classname = classname.lower()
if outputField1 != "":
arcpy.CalculateField_management(targetLayer, outputField1, classname)
#arcpy.AddMessage(str(classname))
#arcpy.AddMessage(str(outputField1))
arcpy.CalculateField_management(targetLayer, outputField2, int(score) )
arcpy.Delete_management("Just_selected")
arcpy.SelectLayerByAttribute_management(targetLayer, "CLEAR_SELECTION")
except:
arcpy.AddMessage("Function failed")
arcpy.AddMessage(arcpy.GetMessages())
the problem appears when the variable classname is equal to "Virtual Flow":
classname = "Virtual Flow"
in the following line taken from the code above
if outputField1 != "":
arcpy.CalculateField_management(targetLayer, outputField1, classname)
From the syntax in the esri help:
CalculateField_management (in_table, field, expression, {expression_type}, {code_block})
The third argument is a SQL Expression. Since you are passing a string that may have a space in it, the expression needs to be surrounded by single quotes ' '.
Something like this should work:
if outputField1 != "":
arcpy.CalculateField_management(targetLayer, outputField1, "".join(("'",classname,"'"))

Categories

Resources