Writing to file clause - python

I have a file in which I have people listed as 'ID Name PhoneNumber Address', like this:
1 Mike 0752 Dallas Alley
2 John 0744 Square Avenue
3 Johnny 0923 Corner Street
Whenever I try to delete or modify a person it won't let me do so, unless I added the person during program execution. What I mean is, I run my program, and unless I add the person(via an add method I use) right then, I won't be able to modify my file.
I can add people to the file, like I said, but even then, it doesn't check if the ID already exists, even though I have this set up in my method.
I should mention that I have a class based program, with repository-controller-UI structure. The SAVE function that I have in my repository is:
def save(self, pers):
'''
Saves a person in class Persoana, returns ValueError if the ID already exists
'''
for i in self.__persList:
if(i.idPers == pers.idPers):
raise ValueError("ID already exists: " +str(i.idPers))
self.__persList.append(pers)
I use this function in my Controller, as follows:
def createPerson(self, idPers, nume, telefon, adresa):
'''
Creates a person as long as the data introduced is correct
'''
i = Persoana(idPers, nume, telefon, adresa)
self.__valiPers.validare(i) //checks if the data I put in is alright(name doesn't contain numbers etc.)
self.__repo.save(i)
I use inheritance to make a FileRepository file, which inherits methods/parameters from the initial Repository file.
class AgendaFileRepository(AgendaRepository):
def __init__(self, file_name):
self.__file_name = file_name
AgendaRepository.__init__(self)
self.__load_from_file()
def __write_to_file(self):
l=self.get_persoane()
f=open(self.__file_name,"w")
for person in l:
f.write(repr(person)+'\n')
f.close()
def __load_from_file(self):
try:
f=open(self.__file_name,"r")
linie=f.readline().rstrip('\n')
while linie!="":
attr=linie.split(" ")
a=Persoana(attr[0], attr[1], attr[2],attr[3])
AgendaRepository.save(self, a)
linie=f.readline().rstrip('\n')
f.close()
except IOError:
raise IOError("File cannot be open")
except ValueError:
raise ValueError("Can't read from file")
except IndexError:
raise IndexError("Can't read from file")
def save(self, pers):
AgendaRepository.save(self, pers)
self.__write_to_file()
The function that I have in my UI folder is:
def addPerson(self):
'''
Adds a person to the file, returns value error if the data isn't valid
'''
name=input("Name: ")
telnumber = input("Tel number: ")
adress = input("Adress: ")
idPers=int(input("Id:"))
try:
self.__ctrl.createPerson(idPers, name, telnumber, adress)
print("Added person successfully")
except ValueError as ex:
print(str(ex))
Anyway, I realise that this exercise can be done way easier/faster, but the professor wants to make us understand OOP I guess. Anyway, I can write stuff to the file, but it doesn't check if the ID of the person is there already, unless I added the person during program execution. I can't delete/modify people either, unless they have been added during program execution.
Been busting my brains for like 2 hours now with this, checking every line and everything, but I can't seem to crack it. What am I doing wrong?

Alright, I found the issue. The problem was that the type of i.idPers and pers.idPers wasn't the same. One was a string and the other was an integer, and the equality between them never happened, thus the program never entered the IF loop.

Related

Python adding unique string into array

ok this is more of a conceptual question, but if i have an array of strings, how can i make a condition where i have a program that tracks a chat and prints out the players name, how can i make a condition where i have a loop that prints the players name every time they chat once i turn on the program, but if they chat again, and my program recognizes the familiar name, it wont print their name out again, essentially only printing out that persons name once
userName = "ThePlayersName" # constantly changing
nameTracker = []
if userName not in nameTracker:
print(userName)
I understand the program is wrong, but just assume 'UserName' is constantly changing and the userName is being added to the array, or another way to print out the name only once
Instead of an array, you could use a set, which can contain only distinct elements. You can use nameTracker.add(userName) and it will only add the name if it's not already in the set.
What you have will work just fine.
userName = "ThePlayersName" # constantly changing
nameTracker = []
def printUser(name):
if name not in nameTracker:
print(name)
printUser(userName)
nameTracker.append(userName)
printUser("Player 2")
nameTracker.append("Player 2")
printUser("Player 2")
prints
ThePlayersName
Player 2

tkinter - How to not process further code if error is not fixed - messagebox.showerror()

I have a tkinter app where I have Labels, Entries and Button. Whenever I click the button, the entries get passed to a function where they are verified according to a format.
For example -
Two fields - Employee Name, Employee Id
Now, I wish to check if username starts with "EMP" or not. For that I have made some functions(like checks if alphanumeric or not etc). If the username does not start with "EMP", what I am doing now is showing an error box like this
def tracking_images(self,emp_id,emp_name):
emp_id, emp_name = emp_id.get(), emp_name.get()
if len(emp_id) == 0:
tk.messagebox.showerror("Field error", "Employee ID cannot be empty")
elif len(emp_name) == 0:
tk.messagebox.showerror("Field error", "Employee name cannot be empty")
if not ValidationConditions().first_three_chars(emp_id):
tk.messagebox.showerror("Field error", "Employee ID should start with EMP")
........
........
#Some more code which I don't want user to have until he/she fixes the error from above checks. <-------
Now, after the user clicks "Ok" to any prompt, The code which I don't want user to access still accesses.
How to not user process further until he fixes the errors from the above checks ?
You could approach this in a do-while manner (even if pyhton does not support this semantically)
Pseudo code would look like this:
while True:
ask the name
if the name passes the checks break out of the loop
show errors
code to go to when the name is valid
EDIT: I forgot to note that, as mentioned below, this would have to be done in an extra thread.
Another thing that might work is putting the dialogs in a method that calls itself if the name is invalid to start over.
But I never tried that and cannot test it since I am commuting right now.

Program checks if file exists before it is created

I have a problem with a code i'm writing. One of it's parts is responsible for creating a file, and it is also supposed to tell me if it was successful. If not, it should inform me as well, but the problem is - it checks if the file exists before it gets created. I tried to make a break between creation of file and checking if it exists by using time module (specifically time.sleep option, inserted in almost every place possible), but with no results. I also tried to use another way to check if the file exists. It didn't help. Whole thing works fine (excluding this part), because if the file is already there and i tell the program to create it, it tells me that it was successful, so it can read it properly, but it's too fast. I attached part of my code down below. Thank you in advance.
First way i tried, using os module:
path = 'D:\screen'
os.chdir(path)
exists = os.path.isfile('.\screenshot.png')
exists2 = os.path.isfile('.\screenshot2.png')
And here's the execution part:
def printer():
pyautogui.screenshot('D:\SCREEN\screenshot.png')
time.sleep(3)
if exists:
print("Screenshot was created successfully")
else:
print("Screenshot was not created successfully")
def printer2():
pyautogui.screenshot('D:\SCREEN\screenshot2.png')
time.sleep(3)
if exists2:
print ("Screenshot was created successfully")
else:
print ("Screenshot was not created successfully")
Second way i tried, using pathlib:
path = 'D:/screen'
file1 = Path("D:/screen/screenshot.png")
file2 = Path("D:/screen/screenshot2.png")
And the execution part:
def printer():
pyautogui.screenshot('D:/SCREEN/screenshot.png')
time.sleep(3)
if file1.isfile():
print("Screenshot was created successfully")
else:
print("Screenshot was not created successfully")
def printer2():
pyautogui.screenshot('D:/SCREEN/screenshot2.png')
time.sleep(3)
if file2.isfile():
print("Screenshot was created successfully")
else:
print("Screenshot was not created successfully")
Those variables (file1, file2) were assigned before creating the screenshot, hence they dont exist. screenshot actually returns a PIL image object. So you can check if without even using os.
def printscreen():
try:
image = pyautogui.screenshot('D:/SCREEN/screenshot.png')
except Exception as e:
print(f'Exception occured during screenshotring {str(e)}')
If you want to still check with os if they exist, use it after the screenshot.
pyautogui.screenshot('D:/SCREEN/screenshot.png')
assert os.file.exist('D:/SCREEN/screenshot.png')
I have no idea what pyautogui.screenshot() does but here goes:
Assuming that the first half of each attempt is executed before the printer functions are called, you are storing the result of os.path.isfile() before you've created the file you are testing.
You should also pick a case for the folder name, really it should be in a variable so that you are not typing it twice. You should also use os.path.join instead of typing directory separators.
In printer and printer2 of the first half you should be able to change exists/exists2 to a call to os.path.isfile().
In the simple case this should work:
def printer():
pyautogui.screenshot('D:\screen\screenshot.png') #assume this attempts to create a file
if os.path.isfile('.\screenshot.png'):
print("Screenshot was created successfully")
else:
print("Screenshot was not created successfully")
path = 'D:\screen'
os.chdir(path)
printer()
Welcome to SO!
The best to check if the file exists or not is using a try/catch block.The problem in the code is that their is a race condition between the line os.path.isfile('.\screenshot.png') and the if exists part.
You can try to use the following -
try:
fh = open('.\screenshot.png', 'rw'):
# Do something
except FileNotFoundError:
print("File not found")
Thank you for all of your answers. I was able to deal with my problem by using the solution proposed by Zonyl. It looks like the reason standing behind it was trivial(,,Those variables (file1, file2) were assigned before creating the screenshot" ,,Assuming that the first half of each attempt is executed before the printer functions are called, you are storing the result of os.path.isfile() before you've created the file you are testing.") but i'm thankful you helped me anyway. I hope another newbie in the future may find it useful.

Passing variables through multiple functions python

So I'm trying to make a function that prompts the user for an option, and depending on which option it does something to the information.
Optionone() basically asks the user for information for a single contact, and every time this contact is filled out it creates a list in a list full of the diff contacts.
In optionthree() I am trying to ask a user for a contact they want to display. So once they type in the name of the contact, the code should display the entire list consisting of the contact's information (name, address, phone, email).
I've excluded the other options that are irrelevant to this problem.
contact = []
def optionone():
contactinfo = []
name = str(input("Name: "))
address = str(input("Address: "))
phone = str(input("Phone: "))
email = str(input("Email: "))
contactinfo.append(name)
contactinfo.append(address)
contactinfo.append(phone)
contactinfo.append(email)
contact.append(contactinfo)
contactinfo = []
This is the optionthree function.
def optionthree(contactinfo):
search = input("Name of contact: ")
if search in contactinfo:
print("This is what I'm trying to figure out")
else:
print("There is no contact with that name in your address book.")
return contactinfo
And the main menu function
def menu():
option = int(input("""
Menu Options:
1. Add new contact
2. Display address book
3. Search for contact
4. Modify contact
5. Delete contact
6. Exit
Choose an option: """))
if option == 1:
optionone()
elif option == 3:
info = optionthree(contactinfo)
main()
Right now, when I run this in terminal, it tells me that I'm referencing to the variable contactinfo before it is assigned. The whole concept of parameters and passing variables through functions is very confusing for me; what is wrong in this code?
you use contactinfo in the main function, but didn't define it in the main function. I notice you define a global variable "contact". Not sure if it is the same variable
It looks like you are attempting to reference contactinfo before it gets assigned any values. If you need to have executed option 1 before executing option 3, then you may want option 3 to first check if contactinfo exists. If it doesn't exist, I would suggest writing that line as the following:
info = optionthree(optionone())
Here at Stack Overflow, we handle one problem at a time. In this case, the immediate problem is the undefined variable. Please handle the info look-up in a separate posting, if you still can't figure it out.
I'm going to get rid of extra information for illustration. It's a good programming technique: take little steps. First, we're going to get a name only into the list and be able to find it. You have almost everything hooked up.
The basic principle to remember is that each function has its own "name space" (directory of variables and values). Functions communicate with each other through the parameter list and return values. Yes, there are global variables, too. For now, don't use them.
The purpose of option_one is to add a name to the info list, and make the change available to the main program. You forgot the last part: you have to send back the updated list when you're done:
def option_one(contact_list):
name = str(input("Name: "))
contact_list.append(name)
print("OPT 1 contact_list", contact_list) # trace what you do for debugging purposes.
return contact_list
def menu():
# Menu text omitted
master_list = []
if option == 1:
master_list = option_one(master_list)
print("MAIN ", master_list)
elif option == 3:
info = option_three(master_list)
menu()
Make your main program "own" the master list -- the option functions merely get a copy, do their "thing", and return the updated list (if needed). The main program has to initialize that list, master_list, and hand it off to each chosen function.
Each function has its own little world: what it got from the calling program, the local variables it creates, and what it hands back when it's done. Each routine can call that contact list by whatever local name it chooses; I've called it contact_list (as you did, but with "Pythonic" punctuation).
Output:
Choose an option: 1
Name: Mark
OPT 1 contact_list ['Mark']
MAIN ['Mark']

How can I write to a text file in Python while a user is running a script?

I created a basic game as part of a learning exercise and I'd like to expand it as I learn more Python. The game is a pretty basic, text-based adventure game and some rooms let users pick up items.
I want to write those items to a text file as the user plays and then give the user an option to check his/her 'inventory' during the game. I can't get the syntax right that will enable the script to do the following:
Create a new text file when the user starts a game;
Write defined items to the text file as the user reaches that part of the game;
Create an option to view the inventory (I have an idea how to do this).
Here is an example of part of the script with my attempt at the code for this commented out:
def room1_creep():
print "You slowly enter the room, and look around. In the opposite corner of the room, you see a ferocious looking bear. It doesn't seem to have seen you yet."
print "You make your way to the chest at the end of the room, checking to see whether the bear has seen you yet. So far, so good."
print "Just as you reach the treasure chest, you hear a roar from the bear that seems to have seen you. What do you do? Rush 'back' to the door or go for the 'treasure'?"
creep_choice = raw_input("You have two choices: 'back' or 'treasure'. > ")
if creep_choice == "back":
print "You make a run for it. You feel the bear's hot breath on the back of your neck but you reach the door before it catches you."
print "You slam the door closed behind you and you find yourself back in the passage."
return entrance()
elif creep_choice == "treasure":
print "You manage to grab a few handfuls of gold coins before the bear stabs its claws into you and sprint for the exit."
# inv = open("ex36_game_txt.txt", 'w')
# line3 = raw_input("10 gold coins")
# inv.write(line3)
# inv.write("\n")
# inv.close()
# I also want to add "gold coins" to a text file inventory that the script will add to.
print "You manage to slam the door closed just as the bear reaches it. It howls in frustration and hunger."
return middle()
else:
room1_indecision()
My script is on GitHub if the full script would be useful. I ran a couple searches here and the question that comes closest to what I think I need is this one. I can't work out how to implement this effectively
One of my main challenges is working out how to get the script to create a new text file dynamically and then populate that text file with the items from the inventory.
If you need to write to files in python use with open(...):
...
elif creep_choice == "treasure":
print "You manage to grab a few handfuls of gold coins before the bear stabs its claws into you and sprint for the exit."
with open("ex36_game_txt.txt", 'w') as inv:
line3 = "10 gold coins"
inv.write(line3)
# I also want to add "gold coins" to a text file inventory that the script will add to.
print "You manage to slam the door closed just as the bear reaches it. It howls in frustration and hunger."
return middle()
...
with open will automatically handle exceptions and close file when you finish writing to it.
If you need to a list of defined items you can initialize a dictionary and keep it in the memory like this:
list_of_items = {item0: "...", item1: "...", ...}
Define it in a separate module and import it when you need. Then you can access its values by key and write them to the inventory during the game.
I am not sure what exactly you mean by creating an option to view and inventory. Why not use raw_input() as you already do and check for word inventory?
options = ('1. Inventory.\n'
'2. Save.\n'
'3. Exit.\n')
option = raw_input("Choose an option: {}".format(options))
if option == "Inventory":
with open("ex36_game_txt.txt", "r") as inv:
for item in inv:
print(inv)
It will print out the contents of your inventory file.
Also note that if you plan to run your game in python3, then don't use raw_input() and use input() instead.
You do not need to write to a text file if you use the singleton design pattern. It guarantees that a class always returns one unique instance of itself. Thus you can create a class called "PlayerInventory", and once it has been instanciated at least once, whenever and wherever in your code you try to instantiate your inventory class, it will always return the same instance.
If you wish to make your inventory persistent, so that a player can save a game and get his inventory back after closing the program, use the module called "pickle" to serialize your inventory object directly when exiting.
Example:
class PlayerInventory(object):
_instance = None
def __new__(class_, *args, **kwargs):
if not isinstance(class_._instance, class_):
class_._instance = object.__new__(class_, *args, **kwargs)
# you need to initialize your attributes here otherwise they will be erased everytime you get your singleton
class_._instance.gold_coins = 0
class_._instance.magic_items = []
# etc... whatever stuff you need to store !
return class_._instance
You can write this class in a separate file and import it whenever you need to access your inventory. Example usecase (assuming your wrote this class in a file called "inventory.py", which is contained in your main package called "mygame"):
from mygame.inventory import PlayerInventory
# Adding coins to inventory
if has_won_some_gold:
PlayerInventory().gold_coins += 10
Somewhere else in you code, you might want to check if the player has enough gold to perform a certain action:
from mygame.inventory import PlayerInventory
if PlayerInventory().gold_coins < 50:
print "Unfortunately, you do not possess enough wealth for this action..."
else:
# Whatever you wish ...
Appending something to a list of items:
from mygame.inventory import PlayerInventory
if player_picked_up_sword:
print "Got: 1 bastard sword"
PlayerInventory().magic_items.append("bastard sword")
Note that the import line is only necessary once per file if you put it at the very beggining !

Categories