Python data will not input into CSV file - python

I am working on a project for my shop that would allow me to track dimensions for my statistical process analysis. I have a part with 2 dimensions that I will measure 5 samples for. The dimension are OAL (Over All Length) and a Barb Diameter. I got Python and tKinter to create the window and put all the data into the correct place, but it will not export to the CSV file. It keeps telling me that the name is not defined, but the variable does exist and if I use a print command, the correct value comes up in the shell. So I know the variable exists I'm not sure if it's because I'm using tKinter or not. Any help would be appreciated.
import time
from tkinter import *
import threading
import csv
import datetime
def gui():
root = Tk()
root.title("Troy Screw Products")
titleLabel = Label(root,text="Inspection Worksheet")
partNumLabel = Label(root,text="Part #68800")
now = datetime.datetime.now()
typeLabel = ["Barb Dia","Barb Dia","OAL","Knurl","Threads","Chamfer","OD","OD","OD"]
dimLabel = [".356",".333",".437",".376","n/a",".258",".337",".321",".305"]
tolLabel = [".354/.358",".331/.335",".433/.441",".374/.378","1/4-20",".252/.263",".335/.339",".319/.323",".303/.307"]
observations = ["Obs 1","Obs 2","Obs 3","Obs 4","Obs 5"]
cd1Obs = []
Label(text="Inspection Worksheet").grid(row=0,column=0)
Label(text="Part #68800").grid(row=1,column=0)
r=0
for c in typeLabel:
Label(text=c,relief=RIDGE,width=15).grid(row=2,column=r)
r=r+1
r=0
for c in dimLabel:
Label(text=c,relief=RIDGE,width=15).grid(row=3,column=r)
r=r+1
r=0
for c in tolLabel:
Label(text=c,relief=RIDGE,width=15).grid(row=4,column=r)
r=r+1
r=0
for c in tolLabel:
Checkbutton(width=15).grid(row=5,column=r)
r=r+1
Label(text="").grid(row=6,column=1)
Label(text="").grid(row=7,column=1)
Label(text="OAL").grid(row=8,column=2)
Label(text="Barb Dia").grid(row=8,column=6)
r=9
for c in observations:
Label(text=c,width=15).grid(row=r,column=1)
Label(text=c,width=15).grid(row=r,column=5)
r=r+1
dimOneOb1=StringVar()
dimOneOb2=StringVar()
dimOneOb3=StringVar()
dimOneOb4=StringVar()
dimOneOb5=StringVar()
dimTwoOb1=StringVar()
dimTwoOb2=StringVar()
dimTwoOb3=StringVar()
dimTwoOb4=StringVar()
dimTwoOb5=StringVar()
Entry(textvariable=dimOneOb1).grid(row=9,column=2)
Entry(textvariable=dimOneOb2).grid(row=10,column=2)
Entry(textvariable=dimOneOb3).grid(row=11,column=2)
Entry(textvariable=dimOneOb4).grid(row=12,column=2)
Entry(textvariable=dimOneOb5).grid(row=13,column=2)
Entry(textvariable=dimTwoOb1).grid(row=9,column=6)
Entry(textvariable=dimTwoOb2).grid(row=10,column=6)
Entry(textvariable=dimTwoOb3).grid(row=11,column=6)
Entry(textvariable=dimTwoOb4).grid(row=12,column=6)
Entry(textvariable=dimTwoOb5).grid(row=13,column=6)
def submitEntry():
groupOal1=dimOneOb1.get()
groupOal2=dimOneOb2.get()
groupOal3=dimOneOb3.get()
groupOal4=dimOneOb4.get()
groupOal5=dimOneOb5.get()
groupBarb1=dimTwoOb1.get()
groupBarb2=dimTwoOb2.get()
groupBarb3=dimTwoOb3.get()
groupBarb4=dimTwoOb4.get()
groupBarb5=dimTwoOb5.get()
writeCsv()
Button(text="Submit",command=submitEntry).grid(row=14,column=7)
def writeCsv():
with open("CD 68800 OAL.csv", "a") as cdOal: #open file and give file variable name; r=read, w=write, a=append
cdOalWriter = csv.writer(cdOal) #Give writer a variable name
cdOalWriter.writerow([now.strftime("%Y-%m-%d %H:%M"),groupOal1,groupOal2,groupOal3,groupOal4,groupOal5])
csOal.close()
root.mainloop()
op1 = threading.Thread(target = gui)
op1.start()

Simply pass those variables in the method, writeCsv(). Because the groupOas are local to the submitEntry() function, its called function, writeCsv, does not see such objects. Also, below uses the argument unpack idiom, * of list of objects (I comment out the more verbose lines):
def submitEntry():
groupOal1=dimOneOb1.get()
groupOal2=dimOneOb2.get()
groupOal3=dimOneOb3.get()
groupOal4=dimOneOb4.get()
groupOal5=dimOneOb5.get()
group0as = [groupOal1,groupOal2,groupOal3,groupOal4,groupOal5]
groupBarb1=dimTwoOb1.get()
groupBarb2=dimTwoOb2.get()
groupBarb3=dimTwoOb3.get()
groupBarb4=dimTwoOb4.get()
groupBarb5=dimTwoOb5.get()
writeCsv(*group0as)
# writeCsv(groupOal1,groupOal2,groupOal3,groupOal4,groupOal5)
def writeCsv(a, b, c, d, e):
with open("CD 68800 OAL.csv", "a") as cdOal:
cdOalWriter = csv.writer(cdOal)
cdOalWriter.writerow([now.strftime("%Y-%m-%d %H:%M"), a, b, c, d, e])
csOal.close()

Related

Trace Function not working as intended with imported files

I'm currently working on a program that displays variables line by line as code executes from a file (think trace tables). I'm able to get it working fine when the code is encased within a function inside the program itself but when I import the same code, it tracks new variables that I don't want to track (as they don't appear in the actual script). Is there any way I can isolate the variables specific to the program? (it'll also be useful for when I'm ignoring variables from pulled libraries in Python).
Here's my program so far:
import sys
import dis
from tkinter import *
from PIL import ImageTk, Image
from tkinter import filedialog
line_record = [] #where data on variables will be stored line by line
def trace(frame, event, arg_unused): #tracing function
global line_record
relevant_locals = {}
temp_vars = frame.f_locals.copy()
for k,v in temp_vars.items():
if not k.startswith("__"):
relevant_locals[k] = v
line_record.append([frame.f_lineno, relevant_locals])
return trace
def print_results(v_list):
print_record="" #variable which holds the formatting of the data
for item in v_list: #iterating for data in each recorded line
print_record += "Line " + str(item[0]) + "= "
if item[1]=={}: #catching lines with no variables
print_record += "no variables"
else:
for key in item[1]: #iterating through each variable to fetch associated data
print_record += str(key)+"="+str(item[1].get(key,"error"))+"|"
print_record += "\n"
return print_record
root = Tk() #creating the main window
root.title("frame")
root.iconbitmap("c:/Users/hamza/Documents/Other/Python/GUI/6 images/apple.ico")
root.filename = filedialog.askopenfilename(initialdir="/", title="select file",filetypes=[("python files","*.py")]) #import python files through tkinter dialog box
user_code = compile(open(root.filename, "rb").read(), root.filename, 'exec') #compiling imported code in order to use later in project
sys.settrace(trace)
exec(user_code)
sys.settrace(None)
print(print_results(line_record))
root.mainloop()
And for reference (if needed), my test code is:
a = 1
b = 2
a = a + b
If you need any more information please don't hesitate to ask, I'm happy to clarify, thanks.

How do I use a csv data as variables to apply it for a formula?

I'm trying to use data from a csv file ( https://www.kaggle.com/jingbinxu/sample-of-car-data ). I only need the horsepower and weight columns as variables for the equation: ( 1/4 mile et = 6.290 * (weight/hp) ** .33 ), but it won't apply it. I don't know if the storage is working or I shouldn't do it as a class. When I run the program it doesn't show any errors, but it doesn't show results either. Then I got to plot the results, but I don't think it's even calculating and storing results. Any help is appreciated. Thanks in advance.
Here's the current code i have:
import numpy as np
class car_race_analysis():
def __init__(self, filename):
import numpy as np
self.data = np.genfromtxt(filename,delimiter= ',', skip_header = 1 )
def race_stats(self,w,h):
#cars in data
cars = np.unique(self.data[:,0])
#storage for output
race_times = []
#for each car
for car in cars:
#mask
mask = self.data[:,0] == car
#get data
w = self.data[mask,12]
h = self.data[mask,18]
#apply formula
qrtr_mile = 6.290 * ( w / h ) ** .33
race_times.append(qrtr_mile)
#new atribute
self.race_times = np.array(race_times)
print(race_times)
def trend_plotter(self):
import matlib.pyplot as plt
#inputs
self.race_stats
cars = np.unique(self.data[:,0])
#plot
plt.plot(cars,self.race_times)
plt.xlabel("Car")
plt.ylabel("1/4 Mile Time")
plt.savefig("trend_plot.png")
filename = 'car_data.csv'
Two problems:
I think you meant matplotlib instead of matlib. Make sure you install it pip3 install matplotlib --user and edit your code accordingly.
Your previous code wasn't working because you weren't instantiating a class or running any methods. The only "work" your program did was to define the class and then set a filename variable.
To solve #2, replace your filename=... line with the code below.
Here's what it does:
It checks to see if the file is being run directly (i.e. from command prompt such as python3 <your_file_name>.py. If this class is being imported and used from a different python file, this code would not be executed. More reading: https://www.geeksforgeeks.org/what-does-the-if-name-main-do/
We instantiate a instance of your class and supply the filename variable since that it was your class' __init__ method expects.
We invoke the trend_plotter method on the instance of the class.
if __name__ == '__main__':
filename = 'car_data.csv'
car_analysis = car_race_analysis(filename)
car_analysis.trend_plotter()
Even with those changes, your program will not work because it has other errors. I made a guess at fixing it, which I've pasted below, but I strongly encourage you do diff my changes to understand what I altered to be sure it does what you want.
import numpy as np
import matplotlib.pyplot as plt
class car_race_analysis():
race_times = []
cars = []
def __init__(self, filename):
import numpy as np
self.data = np.genfromtxt(filename, delimiter=',', skip_header=1)
def race_stats(self, w, h):
#cars in data
self.cars = np.unique(self.data[:, 0])
# storage for output
self.race_times = []
# for each car
for car in self.cars:
# mask
mask = self.data[:, 0] == car
# get data
w = self.data[mask, 12]
h = self.data[mask, 18]
# apply formula
qrtr_mile = 6.290 * (w / h) ** .33
self.race_times.append(qrtr_mile)
# new atribute
self.race_times = np.array(self.race_times)
def trend_plotter(self):
# inputs
self.race_stats(len(self.cars), len(self.race_times))
# plot
plt.plot(self.cars, self.race_times)
plt.xlabel("Car")
plt.ylabel("1/4 Mile Time")
plt.savefig("trend_plot.png")
plt.show()
if __name__ == '__main__':
filename = 'car_data.csv'
car_analysis = car_race_analysis(filename)
car_analysis.trend_plotter()

Prolog query in python program not returning correct answers

I am making an expert system in python having a GUI. For that, I have integreted swi-prolog in python using the pyswip library. In the GUI, user selects several values from drop downs (OptionMenu in python). When the variables holding these selected values are passed into the prolog query, " [] " is returned.
However, if instead of the variables, the values(symptoms in this case) are hard coded into the prolog query below, it works fine.
from tkinter import *
from PIL import ImageTk, Image
from pyswip import *
sympList=['--Select Symptom--','headache','sneezing','runny_nose','sore_throat','fever','chills','bodyache','abdominal_pain','loss_of_appetite','skin_rash','conjunctivitus','sweating','vomitting','diarrhea']
class DPDP:
def __init__(self, master):
frame = Frame(master)
frame.grid()
#---------medical symbol pic------------------------
path1 = "Capture.png"
img = ImageTk.PhotoImage(Image.open(path1))
panel = Label(root, image=img)
panel.photo = img
panel.place(x=20,y=20,width=140,height=130)
#----------page title-----------------------------------
mainHeading=Label(master,text="Disease Prediction & Drug Prescribtion ", font=('Verdana 20'), bg='#44689E')
mainHeading.grid(padx=200,pady=60)
#----------symptoms selection---------------------------------------------------
#-------Symptom1-------------------------
symp1=Label(root,text="1st Symptom", font=('Verdana 15'),bg='#44689E')
symp1.place(x=20,y=200)
self.selSymp1=StringVar()
self.selSymp1.set(sympList[0])
sympDropDown1=OptionMenu(root,self.selSymp1,*sympList)
sympDropDown1.place(x=180,y=200)
#-------Symptom2-------------------------
self.symp2=Label(root,text="2nd Symptom", font=('Verdana 15'),bg='#44689E')
self.symp2.place(x=20,y=300)
self.selSymp2=StringVar()
self.selSymp2.set(sympList[0])
sympDropDown2=OptionMenu(root,self.selSymp2,*sympList)
sympDropDown2.place(x=180,y=300)
#-------Symptom3-------------------------
self.symp3=Label(root,text="3rd Symptom", font=('Verdana 15'),bg='#44689E')
self.symp3.place(x=20,y=400)
self.selSymp3=StringVar()
self.selSymp3.set(sympList[0])
sympDropDown3=OptionMenu(root,self.selSymp3,*sympList)
sympDropDown3.place(x=180,y=400)
#-------Symptom4-------------------------
symp4=Label(root,text="4th Symptom", font=('Verdana 15'),bg='#44689E')
symp4.place(x=20,y=500)
self.selSymp4=StringVar()
self.selSymp4.set(sympList[0])
sympDropDown4=OptionMenu(root,self.selSymp4,*sympList)
sympDropDown4.place(x=180,y=500)
bt=Button(frame,text="click",width=5,
command=lambda:queryGenerator(self.selSy
mp1.get(),self.selSymp2.get(),self.selSymp3.get(),
self.selSymp4.get()))
bt.grid(row=4,column=5)
def queryGenerator(s1,s2,s3,s4):
print(s1,s2,s3,s4) #this prints the values that are chosen,correctly
prolog = Prolog()
prolog.consult('kb.pl')
q=list(prolog.query("telldisease(X,s1,s2,s3,s4).")) #prolog query
# for e in q[0].values():
# print("You have " + e)
# break
print(q)
root = Tk()
root.geometry("820x600")
root.resizable(0,0)
root.config(bg='#44689E')
app= DPDP(root)
root.title("DPDP")
root.mainloop()
When the variables holding these selected values are passed into the prolog query, " [] " is returned. However, if instead of the variables, the values(symptoms in this case) are hard coded into the prolog query below, it works fine.
You are passing the literal query "telldisease(X,s1,s2,s3,s4).", but you want to interpolate the values of s1, s2, s3 and s4 into the query string; this can be done e. g. with %-formatting:
q = list(prolog.query("telldisease(X,%s,%s,%s,%s)." % (s1, s2, s3, s4)))

Altering python variable identifiers in a loop which defines a tkinter button

I've got a function in a class in which I am creating several tkinter buttons within, where the number of buttons and the button properties depends on a file (so I can't create a specific number of variables to hold the buttons).
The code I have looks like this (sparing the complexities of the whole code):
import os
import tkinter as tk
Class(GUI):
def ButtonCreator(self):
self.HomeworkList = open("Files\HWNameList.txt", "r")
x = self.HomeworkList.readline()
while not x == "END":
x = x[0:-1]
HomeworkFileName = str("Files\HW-" + x + ".txt")
locals()["self.Button" + x] = tk.Button(master, text = x, command = lambda: self.DisplayHomeworkFile(FileName))
locals()["self.Button" + x].pack()
x = self.HomeworkList.readline()
self.HomeworkList.close()
def DisplayHomeworkFile(self, filename):
os.startfile(filename)
The file I am opening looks like this...
HomeworkName1
HomeworkName2
HomeworkName3
END
When the code runs, it displays the buttons with the correct text written on them but when i click on them they only ever display the file who's file name is written last in the HomeworkList file. Not sure what I've done wrong.
If there is another way to achieve what I'm trying I'm open to all suggestions.
Thanks.
This is a classic beginners problem that comes from misunderstanding how lambda works. For this case you need to use functools.partial.
You also need to forget about modifying locals(). Make a list or dictionary to hold the button instances.
from functools import partial
def ButtonCreator(self):
self.HomeworkList = open("Files\HWNameList.txt", "r")
x = self.HomeworkList.readline()
self.buttons = []
while not x == "END":
x = x[0:-1]
HomeworkFileName = str("Files\HW-" + x + ".txt")
btn = tk.Button(master, text = x, command = partial(self.DisplayHomeworkFile, HomeworkFileName))
btn.pack()
self.buttons.append(btn)
x = self.HomeworkList.readline()
self.HomeworkList.close()

Passing a variable between two functions

The following is a piece of code that I have been working on for awhile. I've been able to compile and run the code without error. However, I am having a difficult time with passing a variable from one function to another in my code.
The problem seems to occur after I run choose() and create self.newLists based on the desired indices. You'll notice that I added print(self.newLists) at the end of this function so that I can check to see if it is producing what I want.
The next function, simplify(), is where my issue arises. When I try to pass self.newLists from the previous function it doesn't seem to produce anything. I also tried printing and/or returning the variable named answer but it returns "none". I've been stumbling over this obstacle for awhile without any progress. Below is the code I am working on along with an example of what I want simplify() to produce.
from tkinter import *
from tkinter.filedialog import askopenfilename
class myFileOpener:
def __init__(self, master):
frame = Frame(master)
frame.pack()
print()
self.newLists = ()
self.printButton = Button(frame, text="Select File", command=self.openfile)
self.printButton.pack(side=LEFT)
self.runButton = Button(frame, text="Run", command=self.combine)
self.runButton.pack(side=LEFT)
self.quitButton = Button(frame, text="Quit", command=frame.quit)
self.quitButton.pack(side=LEFT)
def openfile(self):
filename = askopenfilename(parent=root)
self.lines = open(filename)
# print(self.lines.read())
def choose(self):
g = self.lines.readlines()
for line in g:
matrix = line.split()
JD = matrix[2]
mintime = matrix[5]
maxtime = matrix[7]
self.newLists = [JD, mintime, maxtime]
print(self.newLists)
def simplify(self):
dates = {}
for sub in self.newLists:
date = sub[0]
if date not in dates:
dates[date] = []
dates[date].extend(sub[1])
answer = []
for date in sorted(dates):
answer.append([date] + dates[date])
return answer
def combine(self):
self.choose()
self.simplify()
root = Tk()
b = myFileOpener(root)
root.mainloop()
Example of desired output from simplify():
[['2014-158', '20:07:11.881', '20:43:04.546', '20:43:47.447', '21:11:08.997', '21:11:16.697', '21:22:07.717'],
['2014-163', '17:12:09.071', '17:38:08.219', '17:38:28.310', '17:59:25.649', '18:05:59.536', '18:09:53.243', '18:13:47.671', '18:16:53.976', '18:20:31.538', '18:23:02.243']]
It essentially groups times by certain dates.
You are not producing a list of lists. You are resetting self.newLists each loop iteration, to a single list with 3 elements:
for line in g:
matrix = line.split()
JD = matrix[2]
mintime = matrix[5]
maxtime = matrix[7]
self.newLists = [JD, mintime, maxtime]
You need to instead use list.append() to add those 3 elements to a list you set once, outside of the loop:
self.newLists = []
for line in g:
matrix = line.split()
JD = matrix[2]
mintime = matrix[5]
maxtime = matrix[7]
self.newLists.append([JD, mintime, maxtime])
Your simplify method is adding the individual characters of mintime to your output lists:
for sub in self.newLists:
date = sub[0]
if date not in dates:
dates[date] = []
dates[date].extend(sub[1])
You want to use list.append() there, not list.extend(). That loop can be simplified using dict.setdefault() rather than test for the key manually:
for date, mintime, maxtime in self.newLists:
dates.setdefault(date, []).append(mintime)

Categories

Resources