Perform math equation inside of a loaded text file - python

I'm currently working on a simple little application that keeps track of wins and losses for any sort of game. I'm storing the win/loss count in separate text files as single numbers. What I want the program to be able to do is look into the specified text file, and simply add 1 to the existing number. For example, if the entire text file is simply "0" and I input "win" into the application, it will perform 0+1 and change the text file permanently to the result.
Here's what I've got so far:
ld = open("data/lossdata.txt", "r+")
wd = open("data/windata.txt", "r+")
hlp = open("data/help.txt", "r+")
losread = ld.read()
winread = wd.read()
helpread = hlp.read()
to_write = []
print("Welcome to Track Lad. For help, input \"help\"\nCurrent Win Count: "+winread+"\nCurrent Loss Count: "+losread)
inp = input("Input: ")
if inp == "w" or inp == "win":
for line in wd:
num = int(line) + 1
to_write.append(num)
wd.reload()
wd.seek(0)
for num in to_write:
wd.write(str(num)+'\n')
wd.close()
print("New Win Count: "+winread+"\nLoss Count: "+losread)
input("")
elif inp == "l" or inp == "loss":
ld.write("1")
print("New Loss Count: "+losread+"\nWin Count: "+winread)
input("")
elif inp == "help":
print(helpread)
input("")
else:
print("Invalid input, try again.")
input("")
Everything I've done so far is in the first if statement. I'm not getting any error when I run the code, even when I input "w", but the number in the text file doesn't change. Thanks in advance for any help, and I'll stay on the page to answer any questions that may help you figure out what's wrong.

I would recommend using a single file database like SQLIte instead of separated text files. You also can register all wins and losses (with timestamp, if you needed later).
import sqlite3
db = sqlite3.connect('winloss.db')
cursor = db.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS winloss (
id INTEGER PRIMARY KEY AUTOINCREMENT,
t TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
value TEXT
);
''')
db.commit()
def add_value(db, value):
cursor = db.cursor()
cursor.execute("INSERT INTO winloss(value) VALUES(?)", (value, ))
db.commit()
def add_win(db):
add_value(db, "win")
def add_loss(db):
add_value(db, "loss")
def count_value(db, value):
cursor = db.cursor()
cursor.execute("SELECT COUNT(*) FROM winloss where value=?", (value, ))
return cursor.fetchone()[0]
def count_win(db):
return count_value(db, "win")
def count_loss(db):
return count_value(db, "loss")
if __name__ == '__main__':
print "now"
print "win:", count_win(db)
print "loss:", count_loss(db)
print "adding values"
add_win(db)
add_win(db)
add_loss(db)
print "win:", count_win(db)
print "loss:", count_loss(db)
And it is easier to read and understand

As you seem to have very small data in your lossdata.txt and windata.txt, I would preferably do the following :
read the entire file content and store the data into variables (open the file in readmode, read data, then close the file),
overwrite the entire file content with the new value (open the file in writemode, write data, then close the file)
If you need to update a particular line of your file, know that it's better to make a copy of your input file and create the updated file as a new file. This is exactly what fileinput.input(inplace=1) does as noted in this SO answer.
So, try to do something like :
import fileinput
def process(line):
return int(line) + 1
for line in fileinput.input(inplace=1):
print process(line)

Related

Is there any reason the code shouldn't be functioning correctly with the TRY function?

I'm working on a code that analyzes customers shopping for DVDs and CDs and the code seems to be debugged but still won't run properly.
I've tried debugging and even completely restarting the code:
try:
#open file name disks.txt
infile = open('disk.txt', 'r')
#read first line of the file which is the customer name field and display.
customer_name = customer_name.rstrip('\n')
print(code, end='\t')
#Read the spindles field. strip new line character and display
spindles = infile.readline()
spindles = int(spindles)
print(format(spindles, '3.0f'), end='\t')
#Check code and compute payment due.
#increment appropriate counter
if code == "C" or code == "c":
payment_due = spindles * CW_RW_PRICE
cd_customer_counter += 1
elif code == "D" or code == "d":
payment_due = spindles * DVD_RW_PRICE
dvd_customers_counter += 1
else:
payment_due = 0
The code should just be letting me enter in the customer and the number of items they're purchasing to get the payment amount due. Instead, it's telling me the try function is invalid
Here is a link to a nice tutorial on how try-catch blocks work

Print once after for loop

for line in infileStudents:
line = line.rstrip()
parts = line.split(':')
studentID = int(parts[0])
studentName = parts[1]
if studentID == ID:
break
else:
print("No record")
I am trying to search for an ID number in a file and print a message if the ID doesn't exist in the file.
The above code reads each line and prints a message for each line.
How do I print only one message after I read all the IDs in the file?
Please try this code.
idFound = False # variable declared as a flag with default False
for line in infileStudents:
line = line.rstrip()
parts = line.split(':')
studentID = int(parts[0])
studentName = parts[1]
if studentID == ID:
idFound = True # if Id found then changing flag variable to true to handle further excution of the code
break
if idFound: # handling here
print("Id found")
else:
print ("No record")
if line not in infileStudents.read():
print ("No record")
Try this. There is no need to search through every line when you can use in and check if it is in the entire file as a string.
You can check if ID does exist in file's content without iterating on file's lines like this:
if str(ID) in infileStudents.read():
print("Id found")
else:
print("No record")
Iterating in file's lines is useless rather than redundant.

Python: How can I search a text file for a string input by the user that contains an integer?

This is an example of what is on the text file that I am searching:
15 - Project `enter code here`Name
APP_IDENTIFIER=ie.example.example
DISPLAY_NAME=Mobile Banking
BUNDLE_VERSION=1.1.1
HEADER_COLOR=#72453h
ANDROID_VERSION_CODE=3
20 - Project Name
APP_IDENTIFIER=ie.exampleTwo.exampleTwp
DISPLAY_NAME=More Mobile Banking
BUNDLE_VERSION=1.2.3
HEADER_COLOR=#23456g
ANDROID_VERSION_CODE=6
If, for example, the user types in 15, I want python to copy the following info:
ie.example.example
Mobile Banking
1.1.1
#72453h
3
because I need to copy it into a different text file.
I get the user to input a project number (in this example the project numbers are 15 & 20) and then I need the program to copy the app_identifier, display_name, bundle_version and android_version of the project relating to the number that the user input.
How do I get python to search the text file for the number input by the user and only take the needed information from the lines directly below that specific project?
I have a whole program written but this is just one section of it.
I don't really have any code yet to find and copy the specific information I need.
Here is code i have to search for the project ID
while True:
CUID = int(input("\nPlease choose an option:\n"))
if (CUID) == 0:
print ("Project one")
break
elif (CUID) == 15:
print ("Project two")
break
elif (CUID) == 89:
print ("Project three")
break
else:
print ("Incorrect input")
The solution thanks to Conor:
projectFile = open("C:/mobileBuildSettings.txt" , "r")
for line in projectFile:
CUID = str(CUID)
if CUID + " - " in line:
appIdentifier = next(projectFile).split("=")[1]
displayName = next(projectFile).split("=")[1]
bundleVersion = next(projectFile).split("=")[1]
next(projectFile)
androidVersionCode = next(projectFile).split("=")[1]
print (appIdentifier, displayName, bundleVersion, androidVersionCode)
break
projectfile = open("projects", "r")
for line in projectfile:
if CUID in line:
appIdentifier = next(projectfile).split("=")[1]
displayName = next(projectfile).split("=")[1]
bundleVersion = next(projectfile).split("=")[1]
next(projectfile)
androidVersionCode = next(projectfile).split("=")[1]
# Do whatever with the 4 values here, call function etc.
break
Then do with appIdentifier, displayName, bundleVersion & androidVersionCode what you will, they will return just the values after the '='.
Although I would recommend against generically searching for an integer, what if the integer is also in the bundle or android version?
There is no reason to list all individual numbers in a long if..else list. You can use a regular expression to check if a line starts with any digit. If it does, check if it matches the number you are looking for, and if it does not, skip the following lines until you reach your blank line separator.
As soon as you have the data you are looking for, you can use a regular expression again to locate the =, or simply use .find:
import re
numberToLookFor = '18'
with open("project.txt") as file:
while True:
line = file.readline()
if not line:
break
line = line.rstrip('\r\n')
if re.match('^'+numberToLookFor+r'\b', line):
while line and line != '':
if line.find('='):
print line[line.find('=')+1:]
line = file.readline().rstrip('\r\n')
else:
while line and line != '':
line = file.readline().rstrip('\r\n')
Here you go:
while True:
CUID = int(input("\nPlease choose an option:\n"))
if (CUID) == 0:
appid = value.split("APP_IDENTIFIER=")[1] # get the value after "APP_IDENTIFIER="
print appid
output >>> ie.example.example
You can apply the same code for all values there, just change the title before "=".
Get the whole line from text then get only the value after "=" with this code for result output.

Python- Saving Results to a File and Recalling Them

I'm writing a program in Python that will store Student IDs, names, and D.O.B.s.
The program gives the user the ability to remove, add, or find a student. Here is the code:
students={}
def add_student():
#Lastname, Firstname
name=raw_input("Enter Student's Name")
#ID Number
idnum=raw_input("Enter Student's ID Number")
#D.O.B.
bday=raw_input("Enter Student's Date of Birth")
students[idnum]={'name':name, 'bday':bday}
def delete_student():
idnum=raw_input("delete which student:")
del students[idnum]
def find_student():
print "Find"
menu = {}
menu['1']="Add Student."
menu['2']="Delete Student."
menu['3']="Find Student"
menu['4']="Exit"
while True:
options=menu.keys()
options.sort()
for entry in options:
print entry, menu[entry]
selection=raw_input("Please Select:")
if selection =='1':
add_student()
elif selection == '2':
delete_student()
elif selection == '3':
find_students
elif selection == '4':
break
else:
print "Unknown Option Selected!"
The problem I am having is I cannot figure out how to have the program save any added records to a file when the program ends. It also would need to read back the records when the program restarts.
I keep trying to find tutorials for this sort of thing online, but to no avail. Is this the sort of code I'd want to add?:
f = open("myfile.txt", "a")
I'm new to Python so any help would be appreciated. Thanks so much.
It depends, if you want to actually save python objects, check out Pickle or Shelve, but if you just want to output to a text file, then do the following:
with open('nameOfYourSaveFile', 'w') as saveFile:
#.write() does not automatically add a newline, like print does
saveFile.write(myString + "\n")
Here's an answer that explains the different arguments to open, as in w, w+, a, etc.
As an example, say we have:
with open('nameOfYourSaveFile', 'w') as saveFile:
for i in xrange(10):
saveFile.write(name[i] + str(phoneNumber[i]) + email[i] + "\n")
To read the file back, we do:
names = []
numbers = []
emails = []
with open('nameOfYourSaveFile', 'r') as inFile:
for line in inFile:
#get rid of EOL
line = line.rstrip()
#random example
names.append(line[0])
numbers.append(line[1])
emails.append(line[2])
#Or another approach if we want to simply print each token on a newline
for word in line:
print word
import pickle,os
if os.path.exists("database.dat"):
students = pickle.load(open("database.dat"))
else:
students = {}
... #your program
def save():
pickle.dump(students,open("database.dat","w"))

Search through directories for specific Excel files and compare data from these files with inputvalues

The task:
The firm I have gotten a summer-job for has an expanding test-database that consists of an increasing number of subfolders for each project, that includes everything from .jpeg files to the .xlsx's I am interested in. As I am a bit used to Python from earlier, I decided to give it a go at this task. I want to search for exceldocuments that has "test spreadsheet" as a part of its title(for example "test spreadsheet model259"). All the docs I am interested in are built the same way(weight is always "A3" etc), looking somewhat like this:
Model: 259
Lenght: meters 27
Weight: kg 2500
Speed: m/s 25
I want the user of the finished program to be able to compare results from different tests with each other using my script. This means that the script must see if there is an x-value that fits both criteria at once:
inputlength = x*length of model 259
inputweight = x*weight of model 259
The program should loop through all the files in the main folder. If such an X exists for a model, I want the program to return it to a list of fitting models. The x-value will be a variable, different for each model.
As the result I want a list of all files that fits the input, their scale(x-value) and possibly a link to the file.
For example:
Model scale Link
ModelA 21.1 link_to_fileA
ModelB 0.78 link_to_fileB
The script
The script I have tried to get to work so far is below, but if you have other suggestions of how to deal with the task I'll happily accept them. Don't be afraid to ask if I have not explained the task well enough. XLRD is already installed, and I use Eclipse as my IDE. I've been trying to get it to work in many ways now, so most of my script is purely for testing.
Edited:
#-*- coding: utf-8 -*-
#Accepts norwegian letters
import xlrd, os, fnmatch
folder = 'C:\eclipse\TST-folder'
def excelfiles(pattern):
file_list = []
for root, dirs, files in os.walk(start_dir):
for filename in files:
if fnmatch.fnmatch(filename.lower(), pattern):
if filename.endswith(".xls") or filename.endswith(".xlsx") or filename.endswith(".xlsm"):
file_list.append(os.path.join(root, filename))
return file_list
file_list = excelfiles('*tst*') # only accept docs hwom title includes tst
print excelfiles()
How come I only get one result when I am printing excelfiles() after returning the values, but when I exchange "return os.path.join(filename)" with "print os.path.join(filename)" it shows all .xls files? Does this mean that the results from the excelfiles-function is not passed on? Answered in comments
''' Inputvals '''
inputweight = int(raw_input('legg inn vekt')) #inputbox for weight
inputlength = int(raw_input('legg inn lengd')) #inputbox for lenght
inputspeed = int(raw_input('legg inn hastighet')) #inputbox for speed
'''Location of each val from the excel spreadsheet'''
def locate_vals():
val_dict = {}
for filename in file_list:
wb = xlrd.open_workbook(os.path.join(start_dir, filename))
sheet = wb.sheet_by_index(0)
weightvalue = sheet.cell_value(1, 1)
lenghtvalue = sheet.cell_value(1, 1)
speedvalue = sheet.cell_value(1, 1)
val_dict[filename] = [weightvalue, lenghtvalue, speedvalue]
return val_dict
val_dict = locate_vals()
print locate_vals()
count = 0
Any ideas of how I can read from each of the documents found by the excelfiles-function? "funcdox" does not seem to work. When I insert a print-test, for example print weightvalue after the weightvalue = sheet.cell(3,3).value function, I get no feedback at all. Errormessages without the mentioned print-test:Edited to the script above, which creates a list of the different values + minor changes that removed the errormessages
Script works well until this point
Made some minor changes to the next part. It is supposed to scale an value from the spreadsheet by multiplying it with a constant (x1). Then I want the user to be able to define another inputvalue, which in turn defines another constant(x2) to make the spreadsheetvalue fit. Eventually, these constants will be compared to find which models will actually fit for the test.
'''Calculates vals from excel from the given dimensions'''
def dimension(): # Maybe exchange exec-statement with the function itself.
if count == 0:
if inputweight != 0:
exec scale_weight()
elif inputlenght != 0:
exec scale_lenght()
elif inputspeed != 0:
exec scale_speed()
def scale_weight(x1, x2): # Repeat for each value.
for weightvalue in locate_vals():
if count == 0:
x1 * weightvalue == inputweight
count += 1
exec criteria2
return weightvalue, x1
elif count == 2:
inputweight2 = int(raw_input('Insert weight')) #inputbox for weight
x2 * weightvalue == inputweight2
return weightvalue, x2
The x1 and x2 are what I want to find with this function, so I want them to be totally "free". Is there any way I can test this function without having to insert values for x1 and x2 ?
def scale_lenght(): # Almost identical to scale_weight
return
def scale_speed(): # Almost identical to scale_weight
return
def criteria2(weight, lenght, speed):
if count == 1:
k2 = raw_input('Criteria two, write weight, length or speed.')
if k2 == weight:
count += 1
exec scale_weight
elif k2 == lenght:
count += 1
exec scale_lenght
elif k2 == speed:
count += 1
exec scale_speed
else:
return
Do you see any easier way to deal with this problem?(Hope I managed to explain it well enough. The way I have written the code so far is quite messy, but since I'm not that experienced I'll just have to make it work first, and then clean it up if I have the time.
Since probably none of the values will exactly fit for both x-constants, I thought I'd use approx_Equal to deal with it:
def approx_Equal(x1, x2, tolerance=int(raw_input('Insert tolerance for scaling difference')),err_msg='Unacceptable tolerance', verbose = True ): # Gives the approximation for how close the two values of x must be for
if x1 == x2:
x = x1+ (x2-x1)/2
return x
Eventually, I'd like a diagram of all the variables used + a link-to-file and name for each document.
No sure how I will do this, so any tips are greatly appreciated.
Thanks!
In answer to the first question "How come I only get one result when I am printing excelfiles()" this is because your return statement is within the nested loop, so the function will stop on the first iteration. I would try building up a list instead and then return this list, you could also combine this with the issue of checking the name e.g. :
import os, fnmatch
#globals
start_dir = os.getenv('md')
def excelfiles(pattern):
file_list = []
for root, dirs, files in os.walk(start_dir):
for filename in files:
if fnmatch.fnmatch(filename.lower(), pattern):
if filename.endswith(".xls") or filename.endswith(".xlsx") or filename.endswith(".xlsm"):
file_list.append(os.path.join(root, filename))
return file_list
file_list = excelfiles('*cd*')
for i in file_list: print i
Obviously, you'll need to replace the cd with your own search text, but keep the * either side and replace the start_dir with your own. I have done the match on filename.lower() and entered the search text in lower case to make the matching case in-sensitive, just remove the .lower() if you don't want this. I have also allowed for other types of Excel files.
Regarding reading data from Excel files I have done this before to create an automated way of converting basic Excel files into csv format. You are welcome to have a look at the code below and see if there is anything you can use from this. The xl_to_csv function is where the data is read from the Excel file:
import os, csv, sys, Tkinter, tkFileDialog as fd, xlrd
# stop tinker shell from opening as only needed for file dialog
root = Tkinter.Tk()
root.withdraw()
def format_date(dt):
yyyy, mm, dd = str(dt[0]), str(dt[1]), str(dt[2])
hh, mi, ss = str(dt[3]), str(dt[4]), str(dt[5])
if len(mm) == 1:
mm = '0'+mm
if len(dd) == 1:
dd = '0'+dd
if hh == '0' and mi == '0' and ss == '0':
datetime_str = dd+'/'+mm+'/'+yyyy
else:
if len(hh) == 1:
hh = '0'+hh
if len(mi) == 1:
mi = '0'+mi
if len(ss) == 1:
ss = '0'+ss
datetime_str = dd+'/'+mm+'/'+yyyy+' '+hh+':'+mi+':'+ss
return datetime_str
def xl_to_csv(in_path, out_path):
# set up vars to read file
wb = xlrd.open_workbook(in_path)
sh1 = wb.sheet_by_index(0)
row_cnt, col_cnt = sh1.nrows, sh1.ncols
# set up vars to write file
fileout = open(out_path, 'wb')
writer = csv.writer(fileout)
# iterate through rows and cols
for r in range(row_cnt):
# make list from row data
row = []
for c in range(col_cnt):
#print "...debug - sh1.cell(",r,c,").value set to:", sh1.cell(r,c).value
#print "...debug - sh1.cell(",r,c,").ctype set to:", sh1.cell(r,c).ctype
# check data type and make conversions
val = sh1.cell(r,c).value
if sh1.cell(r,c).ctype == 2: # number data type
if val == int(val):
val = int(val) # convert to int if only no decimal other than .0
#print "...debug - res 1 (float to str), val set to:", val
elif sh1.cell(r,c).ctype == 3: # date fields
dt = xlrd.xldate_as_tuple(val, 0) # date no from excel to dat obj
val = format_date(dt)
#print "...debug - res 2 (date to str), val set to:", val
elif sh1.cell(r,c).ctype == 4: # boolean data types
val = str(bool(val)) # convert 1 or 0 to bool true / false, then string
#print "...debug - res 3 (bool to str), val set to:", val
else:
val = str(val)
#print "...debug - else, val set to:", val
row.append(val)
#print ""
# write row to csv file
try:
writer.writerow(row)
except:
print '...row failed in write to file:', row
exc_type, exc_value, exc_traceback = sys.exc_info()
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
for line in lines:
print '!!', line
print 'Data written to:', out_path, '\n'
def main():
in_path, out_path = None, None
# set current working directory to user's my documents folder
os.chdir(os.path.join(os.getenv('userprofile'),'documents'))
# ask user for path to Excel file...
while not in_path:
print "Please select the excel file to read data from ..."
try:
in_path = fd.askopenfilename()
except:
print 'Error selecting file, please try again.\n'
# get dir for output...
same = raw_input("Do you want to write the output to the same directory? (Y/N): ")
if same.upper() == 'Y':
out_path = os.path.dirname(in_path)
else:
while not out_path:
print "Please select a directory to write the csv file to ..."
try:
out_path = fd.askdirectory()
except:
print 'Error selecting file, please try again.\n'
# get file name and join to dir
f_name = os.path.basename(in_path)
f_name = f_name[:f_name.find('.')]+'.csv'
out_path = os.path.join(out_path,f_name)
# get data from file and write to csv...
print 'Attempting read data from', in_path
print ' and write csv data to', out_path, '...\n'
xl_to_csv(in_path, out_path)
v_open = raw_input("Open file (Y/N):").upper()
if v_open == 'Y':
os.startfile(out_path)
sys.exit()
if __name__ == '__main__':
main()
Let me know if you have any questions on this.
Finally, regarding the output I would consider writing this out to a html file in a table format. Let me know if you want any help with this, I will have some more sample code that you could use part of.
UPDATE
Here is some further advice on writing your output to a html file. Here is a function that I have written and used previously for this purpose. Let me know if you need any guidance on what you would need to change for your implementation (if anything). The function expects a nested object in the data argument e.g. a list of lists or list of tuples etc. but should work for any number of rows / columns:
def write_html_file(path, data, heads):
html = []
tab_attr = ' border="1" cellpadding="3" style="background-color:#FAFCFF; text-align:right"'
head_attr = ' style="background-color:#C0CFE2"'
# opening lines needed for html table
try:
html.append('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" ')
html.append('"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> ')
html.append('<html xmlns="http://www.w3.org/1999/xhtml">')
html.append('<body>')
html.append(' <table'+tab_attr+'>')
except:
print 'Error setting up html heading data'
# html table headings (if required)
if headings_on:
try:
html.append(' <tr'+head_attr+'>')
for item in heads:
html.append(' '*6+'<th>'+str(item)+'</th>')
html.append(' </tr>')
except:
exc_type, exc_value, exc_traceback = sys.exc_info()
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
print 'Error writing html table headings:'
print ''.join('!! ' + line for line in lines)
# html table content
try:
for row in data:
html.append(' <tr>')
for item in row:
html.append(' '*6+'<td>'+str(item)+'</td>')
html.append(' </tr>')
except:
print 'Error writing body of html data'
# closing lines needed
try:
html.append(' </table>')
html.append('</body>')
html.append('</html>')
except:
print 'Error closing html data'
# write html data to file
fileout = open(path, 'w')
for line in html:
fileout.write(line)
print 'Data written to:', path, '\n'
if sql_path:
os.startfile(path)
else:
v_open = raw_input("Open file (Y/N):").upper()
if v_open == 'Y':
os.startfile(path)
headings_on is a global that I have set to True in my script, you will also need to import traceback for the error handling to work as it is currently specified.

Categories