Append not saving for external file in python - python

I'm trying to figure out how to make sure that when I run a new dict entry that it actually saves. Before last exception, when you "print(dictio.fullDict3[firstLetter])", it shows the new appended dict entry, but doesn't actually save in the external file called dictio.
The following is the main:
import fileinput
import dictio
from dictio import fullDict3
while True:
try:
srcTxt = input("Input word you want to look up: ")
firstLetter = srcTxt[0]
print(dictio.fullDict3[firstLetter][srcTxt])
except:
try:
queryInput = input('What does '+srcTxt+' mean?: ')
with open("C:\\Users...\\dictio.py", "a"):
dictio.fullDict3[firstLetter].update({srcTxt:queryInput})
print(dictio.fullDict3[firstLetter])
except:
print("error has occured.")
The following is the external file called dictio.py that holds the dictionary:
fullDict3 = {
'0':{
'0data':'0datttaaa',
'0mada':'0mmmaadaa'
},
'a':{
'arbre':'tree',
'arc-en-ciel':'rainbow'
},
'b':{
'bierre':'beer',
'belle':'beautiful'
}
}

You can't change the contents of a module by operating on the module's contents via import. There is no reason to import fullDict3. Instead, store your starting structure in fullDict3.json. Convert that file to a Python object via json.load -- that returns a dict you can change. When you have the updated dict ready to write to disk, save it via json.dump.

Alright. Haven't had much time to code, but finally fixed my issue after some reading and trial an error, for anyone that comes across this for answers, however, there could easily be a cleaner and more efficient way to get it done:
while True:
try:
srcTxt = input("Input word you want to look up: ")
firstLetter = srcTxt[0]
if srcTxt == "ESC":
break
print(dictio.fullDict3[firstLetter][srcTxt])
except:
try:
queryInput = input('What does '+srcTxt+' mean?: ')
with open('C:\\Users...\\dictio.py', 'r') as f:
fullDict3[firstLetter].update({srcTxt:queryInput})
newDict = "fullDict3 = "+json.dumps(fullDict3)
with open('C:\\Users...\\dictio.py', 'w') as f:
f.write(newDict)
f.close()
except:
print("error has occured.")

Related

Try and except trouble with practice problem getting error

Using try and except, open animals_shortList.txt for reading and read the file data, creating a new list. Sort the list alphabetically. it would look like this temporary. https://i.stack.imgur.com/A7TE9.jpg
Once the list has been successfully created and sorted, loop through each item in the list and prints the animal, phylum, and diet, as shown. Use a variable to number each printed line. it should be shown like this [1]: https://i.stack.imgur.com/e9Wi5.jpg
Code:
import sys
def main():
names = []
phylum = []
diet = []
output = ""
infile = "animals_shortList.txt"
try:
animalFile = open(infile, "r")
except:
print("Must be file", infile)
animalList = infile.readlines()
print(animalList)
fileName.close()
main()
Try it like this :
infile = 'animals_shortList.txt'
try :
with open (infile, 'r') as file :
animalList = file.readlines ()
except :
print ('Must be file ', infile)
print (animalList)

I want to create lists of racer's times on a seperate file using code on another python file

enter code hereBasically, I want to be able to have 2 different files, one with code, one with the times. Every time I enter a runner's name i want it to either
A. Create a new name and times
Like so:
runner1 = [23:43:15, 18:14:16]
OR
B. Update a runners info and add a time to it
Like so:
runner1 = [23:43:15, 18:14:16] but add 19:16:18 to it
But I really need it to save to another file, so even if i shut off the program, it will still save. Everything needs to be updated, no new lists should be created (Unless it doesn't already exist)
Any help would really be appreciated as i have lost countless hours of sleep attempting this!
Here is the code I already have:
Racename = input("Name of the race")
runnerstxt = open("runners.py", "a")
runnerstxt.write(Racename + '\n')
while True:
runnernameandtime = []
runnerName = input("What was the racer's name? ")
runnernameandtime.append(runnerName)
runnerTime = input("What was the racer's time? ")
runnernameandtime.append(runnerTime)
runnerstxt.write(str(runnernameandtime))
runnerstxt.write("\n")
runnernameandtime.clear()```
Let us assume that all your data will be stored in a file called race_data.pickle. We will store all the data in a single dictionary and then can access everything that has previously been stored.
import pickle
# Check if a file exists
try:
# Previous file found, loading it
race_data = pickle.load(open("race_data.pickle", "rb"))
except (OSError, IOError) as e:
race_data = {}
Racename = input("Name of the race")
#Check if the race has previously been registered
if Racename not in race_data.keys():
#Add if not registered
race_data[Racename] = {}
while True:
runnerName = input("What was the racer's name? ")
#Check if the runner has been registered
if runnerName not in race_data[Racename].keys():
#Add empty if not registered
race_data[Racename][runnerName] = []
#Add the runner's time in the list
runnerTime = input("What was the racer's time? ")
race_data[Racename][runnerName].append(runnerTime)
#Save the latest data into the pickle
with open("race_data.pickle", "wb") as f:
pickle.dump(race_data, f)
You can kill the program at any time and it will have the data from the previous time the object was stored. A sample of how the data will be stored is as follows:
{
'Race1': {
'Racer1': ['3', '10'],
'Racer2': ['5', '22'],
'Racer3': ['20']
},
'Race2': {
'Racer4': ['10'],
'Racer1': ['20'],
'Racer10': ['44']
}
}

Verify data on a file

I'm trying to make my life easier on my work, and writing down errors and solutions for that same errors. The program itself works fine when it's about adding new errors, but then I added a function to verify if the error exists in the file and then do something to it (not added yet).
The function doesn't work and I don't know why. I tried to debug it, but still not able to find the error, maybe a conceptual error?
Anyway, here's my entire code.
import sys
import os
err = {}
PATH = 'C:/users/userdefault/desktop/errordb.txt'
#def open_file(): #Not yet used
#file_read = open(PATH, 'r')
#return file_read
def verify_error(error_number, loglist): #Verify if error exists in file
for error in loglist:
if error_number in loglist:
return True
def dict_error(error_number, solution): #Puts input errors in dict
err = {error_number: solution}
return err
def verify_file(): #Verify if file exists. Return True if it does
archive = os.path.isfile(PATH)
return archive
def new_error():
file = open(PATH, 'r') #Opens file in read mode
loglist = file.readlines()
file.close()
found = False
error_number = input("Error number: ")
if verify_error(error_number, loglist) == True:
found = True
# Add new solution, or another solution.
pass
solution = str(input("Solution: "))
file = open(PATH, 'a')
error = dict_error(error_number, solution)
#Writes dict on file
file.write(str(error))
file.write("\n")
file.close()
def main():
verify = verify_file() #Verify if file exists
if verify == True:
new = str.lower(input("New job Y/N: "))
if new == 'n':
sys.exit()
while new == 'y':
new_error()
new = str.lower(input("New job Y/N: "))
else:
sys.exit()
else:
file = open(PATH, "x")
file.close()
main()
main()
To clarify, the program executes fine, it don't return an error code. It just won't execute the way I'm intended, I mean, it supposed to verify if certain error number already exists.
Thanks in advance :)
The issue I believe you're having is the fact that you're not actually creating a dictionary object in the file and modifying it but instead creating additional dictionaries every time an error is added then reading them back as a list of strings by using the .readlines() method.
An easier way of doing it would be to create a dictionary if one doesn't exist and append errors to it. I've made a few modifications to your code which should help.
import sys
import os
import json # Import in json and use is as the format to store out data in
err = {}
PATH = 'C:/users/userdefault/desktop/errordb.txt'
# You can achieve this by using a context manager
#def open_file(): #Not yet used
#file_read = open(PATH, 'r')
#return file_read
def verify_error(error_number, loglist): #Verify if error exists in file
# Notice how we're looping over keys of your dictionary to check if
# an error already exists.
# To access values use loglist[k]
for k in loglist.keys():
if error_number == k:
return True
return False
def dict_error(loglist, error_number, solution): #Puts input errors in dict
# Instead of returning a new dictionary, return the existing one
# with the new error appended to it
loglist[error_number] = solution
return loglist
def verify_file(): #Verify if file exists. Return True if it does
archive = os.path.isfile(PATH)
return archive
def new_error():
# Let's move all the variables to the top, makes it easier to read the function
# Changes made:
# 1. Changed the way we open and read files, now using a context manager (aka with open() as f:
# 2. Added a json parser to store in and read from file in a json format. If data doesn't exist (new file?) create a new dictionary object instead
# 3. Added an exception to signify that an error has been found in the database (this can be removed to add additional logic if you'd like to do more stuff to the error, etc)
# 4. Changed the way we write to file, instead of appending a new line we now override the contents with a new updated dictionary that has been serialized into a json format
found = False
loglist = None
# Open file as read-only using a context manager, now we don't have to worry about closing it manually
with open(PATH, 'r') as f:
# Lets read the file and run it through a json parser to get a python dictionary
try:
loglist = json.loads(f.read())
except json.decoder.JSONDecodeError:
loglist = {}
error_number = input("Error number: ")
if verify_error(error_number, loglist) is True:
found = True
raise Exception('Error exists in the database') # Raise exception if you want to stop loop execution
# Add new solution, or another solution.
solution = str(input("Solution: "))
# This time open in write only and replace the dictionary
with open(PATH, 'w') as f:
loglist = dict_error(loglist, error_number, solution)
# Writes dict on file in json format
f.write(json.dumps(loglist))
def main():
verify = verify_file() #Verify if file exists
if verify == True:
new = str.lower(input("New job Y/N: "))
if new == 'n':
sys.exit()
while new == 'y':
new_error()
new = str.lower(input("New job Y/N: "))
else:
sys.exit()
else:
with open(PATH, "x") as f:
pass
main()
main()
Note that you will have to create a new errordb file for this snippet to work.
Hope this has helped somehow. If you have any further questions hit me up in the comments!
References:
Reading and Writing files in Python
JSON encoder and decoder in Python
I think that there may be a couple of problems with your code, but the first thing that I noticed was that you are saving Error Numbers and Solutions as a dictionary in errorsdb.txt and when you read them back in you are reading them back in as a list of strings:
The line:
loglist = file.readlines()
in new_error returns a list of strings. This means that verify_error will always return False.
So you have a couple of choices:
You could modify verify_error to the following:
def verify_error(error_number, loglist): #Verify if error exists in file
for error in loglist:
if error_number in error:
return True
Although, I think that a better solution would be to load errorsdb.txt as a JSON file and then you'll have a dictionary. That would look something like:
import json
errordb = {}
with open(PATH) as handle:
errordb = json.load(handle)
So here are the full set of changes I would make:
import json
def verify_error(error_number, loglist): #Verify if error exists in file
for error in loglist:
if error_number in error:
return True
def new_error():
errordb = list()
exitsting = list()
with open(PATH) as handle:
existing = json.load(handle)
errordb += existing
error_number = input("Error number: ")
if verify_error(error_number, errordb) == True:
# Add new solution, or another solution.
print("I might do something here.")
else:
solution = str(input("Solution: "))
errordb.append({error_number, solution})
#Writes dict on file
with open(PATH, "w") as handle:
json.dump(errordb, handle)

Writing functions to allow user define file name and enter file contents

I am learning Python as a beginner and have a question that I couldn't figure out. I need to write functions to allow users to setup/give a file a name and then enter contents.
The error message I got is: "Str' object is not callable. I don't know how to fix this. Please could you help me out. Many thanks!
The code is as follows:
=========================================
WRITE = "w"
APPEND = "a"
fName = ""
def fileName(): #to define name of the file.
fName = input("Please enter a name for your file: ")
fileName = open(fName, WRITE)
return fileName
#now to define a function for data entry
dataEntry = ""
def enterData():
dataEntry = input("Please enter guest name and age, separated by a coma: ")
dataFile = open(fName, APPEND(dataEntry))
fName.append(dataEntry)
return dataFile
#to determine if it's the end of data entry
moreEntry = input("Anymore guest: Y/N ")
while moreEntry != "N":
enterData() #here to call function to repeat data entry
fName.close()
fileName()
enterData()
print("Your file has been completed!")
fileContents = fName.readline()
print(fileContents)
I ran the code and... I seeing the error as line 14
14 dataFile = open(fName, APPEND(dataEntry))
APPEND appears to be a str. It does not appear to be a function.
fName is not declared in this scope. Your function spacing is off. Maybe you meant to run the all the code in order rather than in parts?
As it is, fName is declared and defined once globally (line 4), declared and defined in function filename() (line 6).
fName is also referred to in the function (line 7) Called unsuccessfully in line 14
dataFile = open(fName, APPEND(dataEntry)) # fName has not been declared in function enterData()
I suspect your code would work if you reordered your lines and not use functions (due to references) Also, please close your files. EG
f = open ("somefile.txt", "a+")
...
f.close() #all in the same block.
Thanks for all the inputs. Much appreciated. I've reworked the code a bit, and to put all data entry into a list first, then try to append the list to the file. It works, to a certain extent (about 80%, perhaps!)
However, I now have another problem. When I tried to open the file to append the list, it says "No such file or directory" next to the code (line31): "myFile = open(fName, APPEND)". But I thought I declared and then let user define the name at the beginning? How should I make it work, please?
Thanks in advance again!
WRITE = "w"
APPEND = "a"
fName = ""
def fileName(): #to define name of the file.
fName = input("Please enter a name for your file: ")
fileName = open(fName, WRITE)
fileName.close()
return fileName
#now to define a function for data entry
dataEntry = ""
dataList = []
def enterData():
dataEntry = input("Please enter guest name and age, separated by a coma: ")
dataList.append(dataEntry)
return
fileName()
enterData()
#to determine if it's the end of data entry
moreEntry = input("Anymore guest: Y/N ")
if moreEntry == "Y":
enterData()
else:
print("Your file has been completed successfully!")
myFile = open(fName, APPEND)
myFile.append(dataList)
myFile.close()
fileContents = fName.readline()
print(fileContents)

How do I remove a particular line from a file but keep other lines intact?

I want to learn Python so I started writing my first program which is a phone book directory.
It has the options to add a name and phone number, remove numbers, and search for them.
Ive been stuck on the remove part for about 2 days now and just can't get it working correctly. I've been in the Python IRC and everything, but haven't been able to figure it out.
Basically, my program stores the numbers to a list in a file. I cannot figure out how to remove a particular line in the file but keep the rest of the file intact. Can someone please help me with this?
Some people have advised that it will be easier to do if I create a temp file, remove the line, then copy the remaining lines from the original file over to the temp file. Then write over the original file over with the temp file. So I have been trying this...
if ui == 'remove':
coname = raw_input('What company do you want to remove? ') # company name
f = open('codilist.txt', 'r') # original phone number listing
f1 = open('codilist.tmp', 'a') # open a tmp file
for line in f:
if line.strip() != coname.strip():
for line in f:
f1.write(line)
break # WILL LATER OVERWRITE THE codilist.txt WITH THE TMP FILE
else:
f1.write(line)
else:
print 'Error: That company is not listed.'
f1.close()
f.close()
continue
I assume your file contains something like <name><whitespace><number> on each line? If that's the case, you could use something like this for your if statement (error handling not included!):
name, num = line.strip().split()
if name != coname.strip():
# write to file
Suggestion:
Unless there is some specific reason for you to use a custom format, the file format json is quite good for this kind of task. Also note the use of the 'with' statement in these examples, which saves you having to explicitly close the file.
To write the information:
import json
# Somehow build a dict of {coname: num,...}
info = {'companyA': '0123456789', 'companyB': '0987654321'}
with open('codilist.txt', 'w') as f:
json.dump(info, f, indent=4) # Using indent for prettier files
To read/amend the file:
import json
with open('codilist.txt', 'r+') as f:
info = json.load(f)
# Remove coname
if coname in info:
info.pop(coname)
else:
print 'No record exists for ' + coname
# Add 'companyC'
info['companyC'] = '0112233445'
# Write back to file
json.dump(info, f, indent=4)
You'll need python2.6 or later for these examples. If you're on 2.5, you'll need these imports:
import simplejson as json
from __future__ import with_statement
Hope that helps!
Here is a pretty extensively rewritten version:
all the phone data is wrapped into a Phonebook class; data is kept in memory (instead of being saved and reloaded for every call)
it uses the csv module to load and save data
individual actions are turned into short functions or methods (instead of One Big Block of Code)
commands are abstracted into a function-dispatch dictionary (instead of a cascade of if/then tests)
This should be much easier to understand and maintain.
import csv
def show_help():
print('\n'.join([
"Commands:",
" help shows this screen",
" load [file] loads the phonebook (file name is optional)",
" save [file] saves the phonebook (file name is optional)",
" add {name} {number} adds an entry to the phonebook",
" remove {name} removes an entry from the phonebook",
" search {name} displays matching entries",
" list show all entries",
" quit exits the program"
]))
def getparam(val, prompt):
if val is None:
return raw_input(prompt).strip()
else:
return val
class Phonebook(object):
def __init__(self, fname):
self.fname = fname
self.data = []
self.load()
def load(self, fname=None):
if fname is None:
fname = self.fname
try:
with open(fname, 'rb') as inf:
self.data = list(csv.reader(inf))
print("Phonebook loaded")
except IOError:
print("Couldn't open '{}'".format(fname))
def save(self, fname=None):
if fname is None:
fname = self.fname
with open(fname, 'wb') as outf:
csv.writer(outf).writerows(self.data)
print("Phonebook saved")
def add(self, name=None, number=None):
name = getparam(name, 'Company name? ')
number = getparam(number, 'Company number? ')
self.data.append([name,number])
print("Company added")
def remove(self, name=None):
name = getparam(name, 'Company name? ')
before = len(self.data)
self.data = [d for d in self.data if d[0] != name]
after = len(self.data)
print("Deleted {} entries".format(before-after))
def search(self, name=None):
name = getparam(name, 'Company name? ')
found = 0
for c,n in self.data:
if c.startswith(name):
found += 1
print("{:<20} {:<15}".format(c,n))
print("Found {} entries".format(found))
def list(self):
for c,n in self.data:
print("{:<20} {:<15}".format(c,n))
print("Listed {} entries".format(len(self.data)))
def main():
pb = Phonebook('phonebook.csv')
commands = {
'help': show_help,
'load': pb.load,
'save': pb.save,
'add': pb.add,
'remove': pb.remove,
'search': pb.search,
'list': pb.list
}
goodbyes = set(['quit','bye','exit'])
while True:
# get user input
inp = raw_input("#> ").split()
# if something was typed in
if inp:
# first word entered is the command; anything after that is a parameter
cmd,args = inp[0],inp[1:]
if cmd in goodbyes:
# exit the program (can't be delegated to a function)
print 'Goodbye.'
break
elif cmd in commands:
# "I know how to do this..."
try:
# call the appropriate function, and pass any parameters
commands[cmd](*args)
except TypeError:
print("Wrong number of arguments (type 'help' for commands)")
else:
print("I didn't understand that (type 'help' for commands)")
if __name__=="__main__":
main()
Something simple like this will read all of f, and write out all the lines that don't match:
for line in f:
if line.strip() != coname.strip():
f1.write(line)
Ned's answer looks like it should work. If you haven't tried this already, you can set python's interactive debugger above the line in question. Then you can print out the values of line.strip() and coname.strip() to verify you are comparing apples to apples.
for line in f:
import pdb
pdb.set_trace()
if line.strip() != coname.strip():
f1.write(line)
Here's a list of pdb commands.
You probably don't want to open the temp file in append ('a') mode:
f1 = open('codilist.tmp', 'a') # open a tmp file
also, be aware that
for line in f:
...
f1.write(line)
will write everything to the file without newlines.
The basic structure you want is:
for line in myfile:
if not <line-matches-company>:
tmpfile.write(line + '\n') # or print >>tmpfile, line
you'll have to implement <line-matches-company> (there isn't enough information in the question to know what it should be -- perhaps if you showed a couple of lines from your data file..?)
I got this working...
if ui == 'remove':
coname = raw_input('What company do you want to remove? ') # company name
f = open('codilist.txt')
tmpfile = open('codilist.tmp', 'w')
for line in f:
if coname in line:
print coname + ' has been removed.'
else:
tmpfile.write(line)
f.close()
tmpfile.close()
os.rename('codilist.tmp', 'codilist.txt')
continue

Categories