Python: Use local string variable to call remote function [duplicate] - python

This question already has answers here:
Calling a function of a module by using its name (a string)
(18 answers)
Closed 5 years ago.
def runtest(testname):
usrdef_sship = sship_e.get()
usrdef_username = username_e.get()
usrdef_pass = pass_e.get()
testresult = cpdiag.testname(cpdiag.ssh(usrdef_sship, usrdef_username, usrdef_pass))
messagebox.showinfo( "Results", testresult)
#Button for disk Test
disktest = Button(top, text="Disk Test", command = lambda: runtest("diskTest")
disktest.grid(row=3,column=0, sticky=W)
#Button for cpwd Test
cpwdtest = Button(top, text="CPWD Test", command = lambda: runtest("cpwdTest")
cpwdtest.grid(row=4,column=0, sticky=W)
Tried to shrink the code for what is necessary. Full code at https://github.com/elta13/cpdiag. The above code, I've been banging my head on it for some time. I'm fairly new to python and have been learning as needed during this, my first project.
I'm using Tkinter to display 3 entry fields which are working to obtain usrdef variables. Then I'm using several buttons, each will call a function from another local file cpdiag.py. Right now, I have been rewriting function for each remote function I call with the only thing that changes being the line with cpdiag."testname".(cpdaig.ssh"etc".)
Current problems:
If I pass on the button runtest(diskTest), inside runtuest this prints as "function diskTest at x0xxxxx" And the code crashes with it trying to call "cpdiag.testname" which doesn't exist in the other local file cpdiag.py.
So then I figured out I could pass runtest("diskTest"), and it would print inside of runtest(). But runtest still tries to call "cpdiag.testname" from the other file. I'm realizing at this point, I don't understand how to call something remotely with a local variable.
So then I tried passing runtest("cpdiag.diskTest"), for which I incurred "'str' can't be called" or of the like.
How can I pass "testname" into runtest(), where "testname" is a function defined in other file cpdiag.py?!?!?

You can get the instance of the method you want to invoke on the object cpdiag using getattr builtin then invoke the method. Something like below:
your_function = getattr(cpdiag, testname) # Get the method first
# Now invoke
your_function(cpdiag.ssh(usrdef_sship, usrdef_username, usrdef_pass))

Related

Python, function calls within same class for GUI

Hello i am trying to make a simple GUI, i have a button which calls a function to import some excel data, i would then like to process those data in another function within the same class. Below is my code for the two functions, rhe first one imports the data, then i would like to use the data from OpendirREF in the function Confidens. Can anyone help?
def OpendirREF(self):
filePath_REF = str(QtGui.QFileDialog.getOpenFileName(self, 'Single File', '*.xlsx')) # \n *.txt')
fileHandle_REF = os.path.basename(filePath_REF)
data_REF = pd.read_excel(fileHandle_REF)
return data_REF
def Confidens(self):
imported_data = self.OpendirREF()
print imported_data
I believe your asking how to call the function in same class .if so
If you want to refer to it, something like this
classname.OpendirREF(self).

Passing variables between two scripts

So I'm new at multiprocessing and subprocessing and I am not sure if I am doing it right.
I have two scripts. One runs the main GUI, and has buttons that run other scrips. I want my entry boxes to be read by my other script, so that it can change the axis of a graph.For now, I simplified it so that it can print it so I can see that the values are being passed to begin with.
When I run the scrips like this:
###class_testing.py### (main script)
class Amplifier_Data_Analysis:
def saving_graph_stuff(self):
global int_startfreq,int_stopfreq,float_steps,float_add_tick
STARTFREQUENCY = self.Start_Freq.get()
int_startfreq = int(STARTFREQUENCY)
STOPFREQUENCY = self.Stop_Freq.get()
int_stopfreq = int(STOPFREQUENCY)
STEPS = self.Steps.get()
float_steps = float(STEPS)
ADD_TICK = self.Add_Tick.get()
float_add_tick = float(ADD_TICK)
print(int_startfreq,int_stopfreq,float_steps,float_add_tick)
return int_startfreq,int_stopfreq,float_steps,float_add_tick
def testreport(self):
subprocess.Popen([sys.executable,'test.py'])
###test.py###
from class_testing import *
int_startfreq,int_stopfreq,float_steps,float_add_tick = Amplifier_Data_Analysis.saving_graph_stuff()
print(startfrequency)
print(stopfrequency)
I get
int_startfreq,int_stopfreq,float_steps,float_add_tick = Amplifier_Data_Analysis.saving_graph_stuff()
TypeError: saving_graph_stuff() missing 1 required positional argument: 'self'
But when I put self, It says it is not defined which makes sense since it's a different script from the main. The GUI is generated form the PAGE app so it's very lengthy, but this is how it looks like: GUI
How do I pass or read variables between two scripts?
It's a class - you have to initialize it
int_startfreq,int_stopfreq,float_steps,float_add_tick = Amplifier_Data_Analysis().saving_graph_stuff()

function for switching frames in python, selenium

I'm looking for a function that makes it easier to switch between two frames. Right now, every time I need to switch between frames, I'm doing this by the following code:
driver.switch_to.frame(driver.find_element_by_css_selector("frame[name='nav']"))
driver.switch_to.frame(driver.find_element_by_css_selector("frame[name='content']"))
My goal is to get a function that takes an argument just to change nav or content since the rest is basically the same.
What I've already tried is:
def frame_switch(content_or_nav):
x = str(frame[name=str(content_or_nav)] #"frame[name='content_or_nav']"
driver.switch_to.frame(driver.find_element_by_css_selector(x))
But it gives me an error
x = str(frame[name=str(content_or_nav)]
^
SyntaxError: invalid syntax
The way this is written, it's trying to parse CSS code as Python code. You don't want that.
This function is suitable:
def frame_switch(css_selector):
driver.switch_to.frame(driver.find_element_by_css_selector(css_selector))
If you are just trying to switch to the frame based on the name attribute, then you can use this:
def frame_switch(name):
driver.switch_to.frame(driver.find_element_by_name(name))
To switch back to the main window, you can use
driver.switch_to.default_content()

Viewing Local Variables in Spyder's Variable Explorer

I'm new to python and am using Spyder's IDE. One feature I appreciate about it is it's variable explorer. However, based on some research, I found that it only shows global variables. A workaround that I found for that is by using the inspect module:
import inspect
local_vars = {}
def main():
global local_vars
a = 2
b = 4
c = a+b
local_vars = inspect.currentframe().f_locals
return c
main()
This works well, however, I have other functions that are called from within main() and I'd like to see those variables in the variable explorer as well. I mimicked what was done for the variables in the main function and the dict does not appear. I noticed that when I disable the setting to "exclude unsupported data types" in Spyder's variable explorer options, the second dict appears with the right size attribute, however, I am unable to open/view it. Any ideas on a possible work around? This is my first time posting BTW.
Thanks!!
Here is a working example of my issue and I've traced it down to pylab subplots.
import inspect, pylab
mainVars = {}
def main():
global mainVars
a = 1
b = 2
fig = pylab.figure()
subPlot = fig.add_subplot(211) ## line of interest
pylab.close('all')
mainVars = inspect.currentframe().f_locals
main()
When the line of interest is commented out, the dict is created successfully and can be viewed. It appears that the object created using fig.add_subplot() is not being handled properly by the dict. It seems to be an unsupported datatype.
Hope this helps clarify the issue.
Thanks again.
To view the contents of local variables when some of them are unsupported, you have to follow these steps:
Go to the options menu of the Variable Explorer (the last icon from left to right on it).
Select the option called Exclude unsupported data types.
Then you'll see all local variables saved in the f_locals dict, even if you're unable to double click on it.
All of these workarounds are making your code significantly harder to read for outsiders. You have two options to inspect the values of the variables inside your function. First, you could just return the variables you are interested in:
def main():
a = 2
b = 4
c = a+b
return a, b, c
a, b, c = main()
Second, if you just want to check that the function works as expected or debug it, you can debug the function and step into it. So select Run|Debug from the menu instead of running the file directly. Then you can step into the function - the values of the variables will be visible in the variable explorer when the execution is inside the function.

Unbound Local Error python [duplicate]

This question already has answers here:
UnboundLocalError trying to use a variable (supposed to be global) that is (re)assigned (even after first use)
(14 answers)
Closed 9 years ago.
I need help figuring out why I am getting the following error:
Traceback (most recent call last):
File "prawtest3.py", line 25, in <module>
commentMatcher()
File "prawtest3.py", line 13, in commentMatcher
commentCollection.append(comment)
UnboundLocalError: local variable 'commentCollection' referenced before assignment
This is my code. For background information, I am trying to create a reddit bot that compares a persons comments and then pms a user when the person they are monitoring submits a new comment. If you see a problem with the functionality as well, feel free to share your input. I just need to diagnose my code first to get rid of the syntactical errors before worrying about the semantic ones.
import praw
import time
r = praw.Reddit('PRAW related-question monitor by u/testpurposes v 1.0.')
r.login()
user = r.get_redditor('krumpqueen')
commentCollection = []
commentComparison = []
def commentMatcher():
comments = user.get_comments(limit = 4)
for comment in comments:
commentCollection.append(comment)
time.sleep(60)
comments = user.get_comments(limit = 4)
for comment in comments:
commentComparision.append(comment)
if commentCollection[1] != commentComparision[1]:
r.send_message('krumpqueen', 'just made a new comment', 'go check now')
commentCollection = list(commentComparision)
else:
r.send_message('krumpqueen', 'did not made a new comment', 'sorry')
while(True):
commentMatcher()
Your use of commentCollection makes python (incorrectly1) assume that commentCollection is a local (since you have an assignment to it later and no global statement). When you try to append to the local (which hasn't been created yet) python throws the UnboundLocalError.
1Of course, it's not python making an incorrect assumption, That's how the language is designed to work.
You do commentCollection = list(commentComparision) inside of commentMatcher. Because you've done this, Python concludes you have a local name commentCollection.
Your code fails for the same reason that the code
def foo():
bar.append(3)
bar = []
would fail.
To get commentCollection = list(commentComparision) to a) rebind the global name commentCollection, and b) not make it look like this is a local name at all, add global commentCollection as the first line in the definition of commentMatcher.
In serious code, you wouldn't want to manage your state as globals like this, but rather you'd make an object.

Categories