How To Run A Function From Another Class & Use Its Variable? - python

I'm a beginner in Python working on a simple app for our final year project. This is the only part that I can't solve and I would really appreciate your help. I need to take a value from a live updating csv file, fetch the first element and match it with the reference csv. That part is already working. Then I need it to play the corresponding sound as per the playsound. That part is also already working.
However, since it will be situated in a Kivy app, I need to create multiple classes. Some will handle the data processing side and the Kivy part will handle the display part. But my question today focuses on the Python part not in Kivy.
The first class handles the csv, playsound, and numpy matching.
The second class is where I tried to call the functions of the first class to get them running. I also tried to get the where variable present in the first class so that I could use it in an if statement to verify a match and output a text display.
import serial
import sys
import numpy as np
import time
import csv
import os
import string
import collections
from playsound import playsound
from pathlib import Path
import os, sys
#import keyboard
class Identifier:
def csvwriter(self): #function for writing csv file
try:
ser = serial.Serial('COM10', baudrate=9600)
ser.flushInput()
while True:
ser_bytes = ser.readline()
print(ser_bytes)
file = open("letterz5.csv", "a")
file.write(str(ser_bytes))
file.close()
# if keyboard.is_pressed('esc'):
# break;
ser.close
except:
print("Unexpected error:", sys.exc_info()[0])
print("Unexpected error:", sys.exc_info()[1])
def fn_voice(self): #function for parsing and comparing csv file.
count=1
while (count>0):
livecsv=np.genfromtxt("lettera.csv", delimiter=",", skip_header=1, filling_values=np.nan, dtype=int, case_sensitive=True, deletechars='', replace_space=' ')
refcsv=np.genfromtxt("refcsv1.csv", delimiter=",", skip_header=1, filling_values=np.nan, dtype=int, case_sensitive=True, deletechars='', replace_space=' ')
A=np.array(livecsv)
B=np.array(refcsv)
D = B - A[-1]
match= B[np.abs(D).sum(axis=1).argmin()]
where=match[0]
voice=fn_voice(where)
time.sleep(1)
count = count + 1
var=where
if var==1:
A=playsound('audio-alphabet/A.wav',True)
return A
elif var==2:
B=playsound('audio-alphabet/B.wav',True)
return B
elif var==3:
C=playsound('audio-alphabet/C.wav',True)
return C
elif var==4:
D=playsound('audio-alphabet/D.wav',True)
return D
elif var==5:
E=playsound('audio-alphabet/E.wav',True)
return E
elif var==6:
F=playsound('audio-alphabet/F.wav',True)
return F
elif var==7:
G=playsound('audio-alphabet/G.wav',True)
return G
elif var==8:
H=playsound('audio-alphabet/H.wav',True)
return H
elif var==9:
I=playsound('audio-alphabet/I.wav',True)
return I
elif var==10:
J=playsound('audio-alphabet/J.wav',True)
return J
elif var==11:
K=playsound('audio-alphabet/K.wav',True)
return K
elif var==12:
L=playsound('audio-alphabet/L.wav',True)
return L
elif var==13:
M=playsound('audio-alphabet/M.wav',True)
return M
elif var==14:
N=playsound('audio-alphabet/N.wav',True)
return N
elif var==15:
O=playsound('audio-alphabet/O.wav',True)
return O
elif var==16:
P=playsound('audio-alphabet/P.wav',True)
return P
elif var==17:
Q=playsound('audio-alphabet/Q.wav',True)
return Q
elif var==18:
R=playsound('audio-alphabet/R.wav',True)
return R
elif var==19:
S=playsound('audio-alphabet/S.wav',True)
return S
elif var==20:
T=playsound('audio-alphabet/T.wav',True)
return T
elif var==21:
U=playsound('audio-alphabet/U.wav',True)
return U
elif var==22:
V=playsound('audio-alphabet/V.wav',True)
return V
elif var==23:
W=playsound('audio-alphabet/W.wav',True)
return W
elif var==24:
X=playsound('audio-alphabet/X.wav',True)
return X
elif var==25:
Y=playsound('audio-alphabet/Y.wav',True)
return Y
elif var==26:
Z=playsound('audio-alphabet/Z.wav',True)
return Z
os.system("rm lettera.csv")
class LetterAScreen(Identifier):
def identity(self): #I tried to call the functions of Identifier class here but they won't run
fn_voice() #I need the playsound part to only return playsound when the input data is correct
fn_csvwriter()
iden=fn_voice().where #I need to get the variable 'where' from fn_voice() but I can't seem to get it
def verifier(self):
verify=identity.iden
if verify == 1:
print ("correct")
else:
print ("incorrect")
How do I go about this? How do I get all of the first class running, and how do I fetch the where variable so that I can use it in the verifier function? Thank you very much.

In python you cannot access variables like you have done with fn_voice().where.
Read up some more on scope at https://pythonspot.com/scope/.
The solution to your problem will be to assign the where reference (variable) in the class rather than the method.
class Identifier:
where = None
def fn_voice(self):
where = match[0]
Then you will be able to access where like:
Identifier.where
NB. Remember to check if the value of where is None. We can use standard python truth value testing https://docs.python.org/2.4/lib/truth.html.
if Identifier.where:
#Logic if where is not None.

Related

Problem with def and while True function in python

What's wrong with this that ain't working. I have to ask user for command and if command from setAction() is = 'temp' i have to just do delete() but that's not working.
import glob
import os
def setAction(action):
action = input('Mt Manager> ')
def delete():
pattern = r"C:/Users/kpola/AppData/Local/Temp/**/*"
for item in glob.iglob(pattern, recursive=True):
# delete file
print("Deleting:", item)
os.remove(item)
while True:
if setAction('temp'):
delete()
print('Hello world')
else:
quit()
In the function setAction you are only assinging action to temp over and over again. And since setAction has no return statement it will always return None
def setAction(action):
return input('Mt Manager> ') == action
This snipped should return if your input is equal to "temp"

Accessing a variable after being appended in file a.py from a function in file b.py

I have a problem trying to access a variable from file a.py from a function in file b.py. I tried looking around the internet and could not find anything, or I don't know exactly how to look for what I need. I also tried to make another file and update the variable in file c.py, but file b.py still see's the first initialization of the variable. I tried to update the variable in file a.py and afterwards import a.py in the function in b.py.
File a.py
var = []
def run():
a.welcome()
while True:
menu = a.menu()
if menu == 1:
def retrieve_path(source_path):
"""The function takes 1 parameter and checks if the file name exist as well as the file path
Adds the csv data to a variable
source_path (str): Path against whom to check for validity
"""
if not source_path:
print("Invalid file name, Please try again\n")
return
else:
import os
isFile = os.path.isfile(source_path)
if not isFile:
print("Invalid file path\n")
return
else:
with open(source_path, "r") as csv_file:
csv_reader = csv.reader(csv_file, delimiter=',')
for line in csv_reader:
line = list(line)
var.append(line)
if __name__ == "__main__":
run()
file b.py
I tried like this but I get the first initialization of the variable var = []
I first updated var from file a.py and afterwards, I tried to use the function below inside file b.py but still the same result.
from a import var
from a import *
import a
def a_function():
from a import var
from a import *
import a
print(var)
print(a.var)
This prints the first initialization of var which = [] not after it was appended.
If I print var from a, from inside the function it prints it updated.
If I print var from a, from outside the function it prints it updated.
What I don’t understand is, why after updating it, and importing it into b, I still get the first initialization. Debugger didn’t help as well.
I can work around it by adding the function retrieve_path inside b.py and then appending the data in another variable inside file b.py but I would like to know why its not importing var updated with the data.
File b.py
var2 = []
def retrieve_path(source_path):
"""The function takes 1 parameter and checks if the file name exist as well as the file path
Adds the csv data to a variable
source_path (str): Path against whom to check for validity
"""
if not source_path:
print("Invalid file name, Please try again\n")
return
else:
import os
isFile = os.path.isfile(source_path)
if not isFile:
print("Invalid file path\n")
return
else:
with open(source_path, "r") as csv_file:
csv_reader = csv.reader(csv_file, delimiter=',')
for line in csv_reader:
line = list(line)
var.append(line)
var2.append(line)
The reason I didn't use Class if that was one of the solutions, is because I haven't learned that much about Classes and don't know how to use them properly for the time being.
I hope I was quite explicit and you understand my dilemma. Also, have in mind I just started learning Python, so a newbi explanation and solution are more than welcomed.
The correct way is to call the run function before accessing var. Either
import a
a.run
print(a.var)
or:
from a import var, run
run
print(var)
The import statement only runs the content of the module, not the functions declared in it.
The idiomatic way of running a script is indeed what you have in a.py:
if __name__ == "__main__":
run()
And the run function will be called if you use the file like a script with python a.py, because a file that is started directly by the interpretor will be named __main__. But when it is imported, it is named according to the file name. So here it would be a and not main. Said differently, run is never called when a.py is imported.
One possibility would be to end a.py with an unconditional call of run:
...
line = list(line)
var.append(line)
run()
It should be harmless because Python keeps track of the already imported module, and run should be called only once even if the module was imported from multiple places. Yet it would be an anti-pattern, because by convention import should have as few side effects as possible, while run seems to do plenty of actions.
Ok, this is just a part of the project which was for the school, which I finished, but I wanted to make this part with records a little bit different than I've done for the grade. If some function dont make sense, its because the project it is not finished. My only concerned is towards records variable.
main.py
import tui, csv
records = []
def run():
tui.welcome()
while True:
menu = tui.menu()
if menu == 1:
def retrieve_path(source_path):
"""The function takes 1 parameter and checks if the file name exist as well as the file path
Adds the csv data to a variable
source_path (str): Path against whom to check for validity
"""
if not source_path:
print("Invalid file name, Please try again\n")
return
else:
import os
isFile = os.path.isfile(source_path)
if not isFile:
print("Invalid file path\n")
return
else:
with open(source_path, "r") as csv_file:
csv_reader = csv.reader(csv_file, delimiter=',')
for line in csv_reader:
line = list(line)
records.append(line)
tui.started("Data Loading")
retrieve_path(tui.source_data_path())
tui.completed("Data Loading")
if menu == 2:
tui.started("Retrieving data")
process_menu = tui.process_type()
tui.completed("Retrieving data")
if process_menu == 1:
tui.started("Retrieving entity name")
tui.entity_name()
tui.completed("Retrieving entity name")
if process_menu == 2:
tui.started("Retrieving entity details")
entity, cols = tui.entity_details()
tui.list_entity(entity, cols)
tui.completed("Retrieving entity details")
if menu == 3:
print(tui.main_records)
if menu == 4:
break
if __name__ == "__main__":
run()
Second file is:
tui.py
def welcome():
message = "System Management"
print("*" * len(message))
print(message)
print("*" * len(message))
def menu():
main_menu = "-"
while main_menu != "0":
if main_menu == "-":
print('Main Menu:'
'\n1. Load Data'
'\n2. Process Data'
'\n3. Visualise Data'
'\n4. Save Data'
'\n0. Exit')
elif main_menu in "1234":
return int(main_menu)
elif main_menu not in "1234":
error(main_menu)
return None
else:
print('Main Menu:'
'\n1. Load Data'
'\n2. Process Data'
'\n3. Visualise Data'
'\n4. Save Data'
'\n0. Exit')
main_menu = input()
def started(operation):
print("{} has started.\n".format(operation))
def completed(operation):
print("{} has completed.\n".format(operation))
def error(error_msg):
print("Error! {} is not a valid option.".format(error_msg))
def source_data_path():
print("Please enter the path to the source data file:")
source_path = input()
if ".csv" not in source_path:
return None
else:
return source_path
def process_type():
process_menu = "-"
while process_menu != "0":
if process_menu == "-":
print('Process Menu:'
'\n1. Retrieve entity'
'\n2. Retrieve entity details'
'\n3. Categorise entities by type'
'\n4. Categorise entities by gravity'
'\n5. Summarise entities by orbit'
'\n6. Return to Main Menu')
elif process_menu == "6":
menu()
return None
elif process_menu in "12345":
return int(process_menu)
elif process_menu not in "12345":
error(process_menu)
return None
else:
print('Process Menu:'
'\n1. Retrieve entity'
'\n2. Retrieve entity details'
'\n3. Categorise entities by type'
'\n4. Categorise entities by gravity'
'\n5. Summarise entities by orbit'
'\n6. Return to Main Menu')
process_menu = input()
def entity_name():
entity = input("Please enter the name of an entity: ")
return entity
def entity_details():
entity = input("Please enter the name of an entity: ")
indexes = input("Please enter the indexes number (e.g. 0,1,5,7):\n")
return entity, list(indexes)
Please have
First time I did the project I added def retrieve_path(source_path): to tui.py and it worked fine.
What I don't really understand is why is the variable records being appended to, I can print it from within run and outside of run function, but in tui.py i get only records = [] and how to solve this without creating the function retrieve_path in tui.py
This is what it was asked of us at the time being and it was not my personal choice to do it like this.
I am sorry for not pasting everything here and mistyping some parts like == _ main _ .

Python Class Method not returning imported class method?

I have a class which takes in a user choice (below)
from MiniProject1.interfaces.s_selection import SecondarySelection as SS #
imports the secondary_selection function from selections
import MiniProject1.interfaces.newcastle_cm as IT
from MiniProject1.Newcastle.newcastle_cc import ColumnCalculation as CC
class Newcastle:
def __init__(self):
self.key_typed = input(str("Select what you want to do: "))
#staticmethod
def column_or_graph():
if SS.get_input(SS.display_input()) is True:
IT.column_manipulation()
return True
IT.graph_plotting()
return False
def column_selection(self):
if self.key_typed == 1:
CC.total_electricity() # Calls the total_electricity method
elif self.key_typed == 2:
pass
elif self.key_typed == 3:
pass
elif self.key_typed == 4:
pass
elif self.key_typed == 5:
pass
def main():
if Newcastle.column_or_graph() is True:
Newcastle.column_selection(Newcastle())
elif Newcastle.column_or_graph() is False:
Newcastle.graph_plotting(Newcastle())
if __name__ == "__main__":
main()
The first part seems to run without issue, as the imported functions SS.get_input(SS.display_input()) from a class work without any issues and return either True or False, and when they do Newcastle.column_selection(Newcastle()) works as well, as it displays the interface and takes the user input.
So, all that seems to work. But when the user selects 1 it should return the CC.total_electricity() method, but instead it just ends the program.
I've tried return CC.total_electricity() as well, but that just does the same thing as well, and doesn't work. Is there any idea to why this may be? I've been working on it all day.
The CC.total_electricity class method looks like this:
import pandas as pd
class ColumnCalculation:
"""This houses the functions for all the column manipulation calculations"""
#staticmethod
def total_electricity():
"""Calculates the total amount of electricity used per year"""
df = pd.read_csv("2011-onwards-city-elec-consumption.csv", thousands=',')
df.set_index('Date', inplace=True) # Sets index to months
df.loc['Total'] = df.sum() # Creates a new row for the totals of each year
return print(df) # Prints the dataframe
And that has been tried, and tested to work, it's just when I import it it doesn't return anything and ends the program.
You compare the user input to an integer:
if self.key_typed == 1:
Therefore, you need to convert your input into an integer too.
So instead:
self.key_typed = input(str("Select what you want to do: "))
do:
self.key_typed = int(input("Select what you want to do: "))

How can i use my function a_c_t_b()

My code looks like:
def g_b():
items_in_bag = []
done=False
bugout_bag = 'Bug Out Bag'
while done == False:
item = input('What bags do you have? [Enter x to stop]')
items_in_bag.append(item)
if item == 'x':
done = True
items_in_bag.remove('x')
break
else:
continue
items_in_bag.append(bugout_bag)
print("Your bags\n")
print(items_in_bag)
return items_in_bag
def g_c():
coins_in_bag = []
done=False
while done == False:
coin_item = input('What coins do you have? [Enter x to stop]')
if coin_item == 'x':
done = True
break
else:
coins_in_bag.append(coin_item)
continue
print("Your coins\n")
print(coins_in_bag)
return coins_in_bag
def a_c_t_b(items_in_bag, coins_in_bag):
#print('Here are your coins:\n')
#g_c()
#print('Here are your bags:\n')
#print(items_in_bag)
print (items_in_bag,coins_in_bag)
return (items_in_bag,coins_in_bag)
def main():
g_b()
g_c()
a_c_t_b(items_in_bag,coins_in_bag)
main()
However, when i run this code like: import myfile
It gives me an error of:
File ".\myfile.py", line 51, i
a_c_t_b(items_in_bag,coins_in_bag)
NameError: global name 'items_in_bag' is not defined
I'm simply trying to return the values of items_in_bag,coins_in_bag from their respective functions.
Thank you
Please call your functions more sensible names.
To answer your question, your g_b and g_c functions return values, they don't return names. At the point where you call a_c_t_b, Python has no idea what items_in_bag is, because yo'uve never defined it. Python can't know you mean "the value returned from g_b": you have to tell it.
items_in_bag = g_b()
coins_in_bag = g_c()
a_c_t_b(items_in_bag, coins_in_bag)
You are calling g_b and g_c but never catching their returned values.
You can either do:
def main():
items_in_bag = g_b()
coins_in_bag = g_c()
a_c_t_b(items_in_bag, coins_in_bag)
or:
def main():
a_c_t_b(g_b(), g_c())
When you import the module main function is executed (call in last line). And main function use undefined identifiers items_in_bag and coins_in_bag:
def main():
g_b()
g_c()
a_c_t_b(items_in_bag,coins_in_bag)
Probably you want something like
def main():
items_in_bag = g_b()
coins_in_bag = g_c()
a_c_t_b(items_in_bag,coins_in_bag)

Why does my program add ('', ' to the name of my file?

Here is my code (sorry for the messy code):
def main():
pass
if __name__ == '__main__':
main()
from easygui import *
import time
import os
import random
import sys
##multenterbox(msg='Fill in values for the fields.', title=' ', fields=(), values=())
msg = "Enter your personal information"
title = "Credit Card Application"
fieldNames = ["First name",'Last name','email',"Street Address","City","State","ZipCode",'phone','phone 2)']
fieldValues = [] # we start with blanks for the values
fieldValues = multenterbox(msg,title, fieldNames)
# make sure that none of the fields was left blank
def make(x):
xys = x,".acc"
xyzasd = str(xys)
tf = open(xyzasd,'a+')
tf.writelines(lifes)
tf.writelines("\n")
tf.writelines("credits = 0")
tf.close
def add(x):
nl = "\n"
acc = ".acc"
xy = x + acc
exyz = xy
xyz = exyz
xxx = str(xyz)
tf = open('accounts.dat',"a+")
tf.writelines(nl)
tf.writelines(xxx)
tf.close
while 1:
if fieldValues == None: break
errmsg = ""
for i in range(len(fieldNames)-1):
if fieldValues[i].strip() == "":
errmsg += ('"%s" is a required field.\n\n' % fieldNames[i])
if errmsg == "":
break # no problems found
fieldValues = multenterbox(errmsg, title, fieldNames, fieldValues)
names = enterbox(msg= ('confirm FIRST name and the FIRST LETTER of the persons LAST name'))
##txt = "acc"
##na = str(name)
##name = (names)
life = ( str(fieldValues))
lifes = life,'\n'
herro = ("Reply was: %s" % str(fieldValues))
correct = buttonbox(msg=(herro,'\n is that correct'),choices = ('yes','no','cancel'))
if correct == "yes":
make(names)
add(names)
elif correct == "no":
os.system('openacc.py')
time.sleep(0.5)
sys.exit()
else:
os.system('cellocakes-main.py')
sys.exit()
os.system('cellocakes-main.py')
I don't know what the problem is also I am sorry about how sloppy it was programmed I have a white board to help me out still new to programming (I'm only 13) sorry. Personally I think the issue is in the def add area's syntax but because I am still new I don't see the issue personally I am hoping to have a more experienced programmer help me out.
This is an answer not directly answering your question.
Alas, comment fields are STILL not capable to hold formatted code, so I choose this way.
def main():
pass
if __name__ == '__main__':
main()
This is a nice coding pattern, but used by you in a useless way.
It is supposed to prevent executing of the stuff if it is imported as a module and not executed as a script.
Nevertheless, it is not bad to use it always, but then put your code inside the main() function instead of adding it below.
fieldNames = ["First name",'Last name','email',"Street Address","City","State","ZipCode",'phone','phone 2)']
There is a ) too much.
fieldValues = [] # we start with blanks for the values
fieldValues = multenterbox(msg,title, fieldNames)
The second line makes the first one useless, as you don't use fieldValues in-between.
It would be different if you expected multenterbox() to fail and would want [] as a default value.
def make(x):
xys = x,".acc"
xyzasd = str(xys)
tf = open(xyzasd,'a+')
tf.writelines(lifes)
tf.writelines("\n")
tf.writelines("credits = 0")
tf.close
You was already told about this: x, ".acc" creates a tuple, not a string. To create a string, use x + ".acc".
Besides, your close call is no call, because it is missing the (). This one just references the function and ignores the value.
A better way to write this would be (please name your variables appropriately)
with open(xyzs, 'a+') as tf:
tf.writelines(lifes)
tf.writelines("\n")
tf.writelines("credits = 0")
The with statement automatically closes the file, even if an error occurs.
Besides, you use writelines() wrong: it is supposed to take a sequence of strings and write each element to the file. As it doesn't add newlines in-between, the result looks the same,. but in your case, it writes each byte separately, making it a little bit more inefficient.
Additionally, you access the global variable lifes from within the function. You should only do such things if it is absolutely necessary.
def add(x):
Here the same remarks hold as above, plus
xy = x + acc
exyz = xy
xyz = exyz
xxx = str(xyz)
why that? Just use xy; the two assignments do nothing useful and the str() call is useless as well, as you already have a string.
for i in range(len(fieldNames)-1):
if fieldValues[i].strip() == "":
errmsg += ('"%s" is a required field.\n\n' % fieldNames[i])
Better:
for name, value in zip(fieldNames, fieldValues):
if not value.strip(): # means: empty
errmsg += '"%s" is a required field.\n\n' % name
Then:
life = ( str(fieldValues))
makes a string from a list.
lifes = life,'\n'
makes a tuple from these 2 strings.
os.system('openacc.py')
os.system('cellocakes-main.py')
Please don't use os.system(); it is deprecated. Better use the subprocess module.
The problem of the question is here:
# assign the tuple (x, ".acc") to xys
xys = x,".acc"
# now xyzasd is the tuple converted to a string, thus
# making the name of your file into '("content of x", ".acc")'
xyzasd = str(xys)
# and open file named thus
tf = open(xyzasd,'a+')
What you wanted to do is:
# use proper variable and function names!
def make_account(account):
filename = account + '.acc'
the_file = open(filename, 'a+')
....
On the other hand there are other problems with your code, for example the
def main():
pass
if __name__ == '__main__':
main()
is utterly useless.

Categories

Resources