Python. Let's say I define a class and in a script I create an object using that class.
Then I run a method and I get an error.
Can I use a debugger (for example Spyder's) to understand what is going on inside? for example inserting break points in the class definition?
UPDATE
I'm using spyder debugger.
My script looks like this
...
#I select the object class I need
ObjectClass = GetTheRightClass(variable)
#my object is initialized with variable1
my_object_instance = ObjectClass(variable1)
#I perform a calculation with my object
calculation = my_object_instance.calculate()
...
If I place a break point inside the definiton of the method calculate() the debugger doesn't stop there...
Yes, this is possible in multiple IDE's.
For python, a cool project is also pysnooper. If you call the method using the class you want, you can put a decorator #pysnooper before that function.
If you run the script, you can visually debug the code.
Related
I am trying to write a testing program for a python program that takes data, does calculations on it, then puts the output in a class instance object. This object contains several other objects, each with their own attributes. I'm trying to access all the attributes and sub-attributes dynamically with a one size fits all solution, corresponding to elements in a dictionary I wrote to cycle through and get all those attributes for printing onto a test output file.
Edit: this may not be clear from the above but I have a list of the attributes I want, so using something to actually get those attributes is not a problem, although I'm aware python has methods that accomplish this. What I need to do is to be able to get all of those attributes with the same function call, regardless of whether they are top level object attributes or attributes of object attributes.
Python is having some trouble with this - first I tried doing something like this:
for string in attr_dictionary:
...
outputFile.print(outputclass.string)
...
But Python did not like this, and returned an AttributeError
After checking SE, I learned that this is a supposed solution:
for string in attr_dictionary:
...
outputFile.print(getattr(outputclass, string))
...
The only problem is - I want to dynamically access the attributes of objects that are attributes of outputclass. So ideally it would be something like outputclass.objectAttribute.attribute, but this does not work in python. When I use getattr(outputclass, objectAttribute.string), python returns an AttributeError
Any good solution here?
One thing I have thought of trying is creating methods to return those sub-attributes, something like:
class outputObject:
...
def attributeIWant(self,...):
return self.subObject.attributeIWant
...
Even then, it seems like getattr() will return an error because attributeIWant() is supposed to be a function call, it's not actually an attribute. I'm not certain that this is even within the capabilities of Python to make this happen.
Thank you in advance for reading and/or responding, if anyone is familiar with a way to do this it would save me a bunch of refactoring or additional code.
edit: Additional Clarification
The class for example is outputData, and inside that class you could have and instance of the class furtherData, which has the attribute dataIWant:
class outputData:
example: furtherData
example = furtherData()
example.dataIWant = someData
...
with the python getattr I can't access both attributes directly in outputData and attributes of example unless I use separate calls, the attribute of example needs two calls to getattr.
Edit2: I have found a solution I think works for this, see below
I was able to figure this out - I just wrote a quick function that splits the attribute string (for example outputObj.subObj.propertyIWant) then proceeds down the resultant array, calling getattr on each subobject until it reaches the end of the array and returns the actual attribute.
Code:
def obtainAttribute(sample, attributeString: str):
baseObj = sample
attrArray = attributeString.split(".")
for string in attrArray:
if(attrArray.index(string) == (len(attrArray) - 1)):
return getattr(baseObj,string)
else:
baseObj = getattr(baseObj,string)
return "failed"
sample is the object and attributeString is, for example object.subObject.attributeYouWant
For example...
There are several methods that I'd like to treat as 'events', and fire my own functions once they've been called.
I do not manually invoke these.
As someone that's not well-versed with Python, but familiar with C#, I'd ideally like to be able patch into a module method, and either alter functionality, or just callback my own methods.
edit: example added
def my_own_callback_method():
# do something here
# imagine in a large code base there's a method I'd like to target and fire my own callback ...
#
# ... something else invokes a method ('not_my_method') in a third-party module ('core').
def not_my_method():
# the orginial function executes as it would
#
# but I'd like to pre/post callback my own method from my module
my_own_callback_method()
Alternatively, it'd be nice to be able to 'patch' a method and alter its functionality. Example below -
# again, imagine in a large code base there's a method I'd like to target ...
# ... but I'd like to alter the way this method works in my own module.
#
# kind of like...
def my_method(something:str, something_else:int):
# my own method patch of how the original 'not_my_method' should work
def not_my_method(something:str, something_else:int):
return my_method(something, something_else)
If you don't have any control over not_my_method's code it will be (almost?) impossible since you want to actually change its source code.
I believe that the best you can achieve is wrapping it in your own function that calls my_method after it calls not_my_method, but that would be pretty much it.
Perhaps you are looking at it from the wrong angle. It might be easier to patch the actual event that calls not_my_method than patching not_my_method itself.
This question already has answers here:
How can you dynamically create variables? [duplicate]
(8 answers)
Closed 4 years ago.
I have a class for which I want to create instances through a function, but I also want to be able to name the instances with the value of a Tkinter.Entry widget.
The simplified version of that I am trying to achieve is the following:
class vtdiagram():
IO=0.0
IC=0.0
EO=0.0
EC=0.0
IGA=0.0
def printvtvalues(self):
print self.IO
print self.IC
print self.EO
print self.EC
print self.IGA
def createvtinstance():
global Nametemp
Nametemp=vtdiagram()
If I run this code, then I can call Nametemp.printvtvalues() and get all values printed, so it works fine.
I am now trying to change the name of the instance Nametemp to the string that is on the Tkinter entry widget. Basically, if engine1 is written on the entry box when I createvtinstance(), I would like to then call the instance by:
engine1.printvtvalues()
and get the values.
I imagine the function should look something like this:
def createvtinstance():
global Nametemp
Nametemp=vtdiagram()
Nametemp._command_to_change_the_name_=stringinentrybox.get()
Do you guys have know of a command that can do such a thing?
Or is there a way that I could achieve the same effect, maybe using a dictionary?
***edit: The reason I need to name the variables is for the following (in plain English): I am creating an 'engine simulator'.
The idea is that the user will enter engine parameters -plus its name- in a GUI and this is the vtdiagram class.
The reason for using a class is that I have the characteristics of 'engine1, engine2...' saved as an instance of the class but I also need to have functions attached to it. This is because I want to generate graphs and diagrams of saved engines but only when called. So I can compare engine1 and engine2, but then get 'forget' engine2 from the GUI to compare 1 and 3.
Please keep in mind I am quite new to python :) ***
Many thanks!
Juan
I wouldn't recommend changing the name of a variable based on user input.
You could "achieve the same effect" like this:
Objects=[]
Names=[]
def createvtinstance(Object=4,Name="engine1"):
global Nametemp
global Objects
global Names
Nametemp=Object # I'll just use an int to demonstrate.
Objects+=[Nametemp]
Names+=[Name]
def Use(Name="engine1"):print(Objects[Names.index(Name)]) # Or: Objects[Names.index(Name)].SomeFunction()
If you REALLY want to alter the name of a variable based on user input, then you could do it like this:
def createvtinstance(Name="engine1"):
if (not Name[0]in"qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM") or False in(i in"1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"for i in Name) or Name in("tkinter","createvtinstance","Name","vtdiagram",):return "Invalid name." # This should make the code more "robust".
try:exec("global "+Name+"\n"+Name+"=vtdiagram()")
except SyntaxError:return "Invalid name."
Or this:
def createvtinstance(Name="engine1"):
if (not Name[0]in"qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM") or False in(i in"1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"for i in Name) or Name in("tkinter","createvtinstance","Name","vtdiagram",):raise NameError("The name "+Name+" does not comply to validation rules.") # This should make the code more "robust".
try:exec("global "+Name+"\n"+Name+"=vtdiagram()")
except SyntaxError:raise NameError(Name+" is a reserved keyword.")
The top example shows how you would use a list to find an object in another list; using a string. This is what I'd probably do in this situation, however a dictionary could be better.
The bottom examples show how you would actually name a variable based on user input. This is NOT RECOMMENDED. Everyone seems to agree that using exec is counterproductive, and should be avoided. Python can't compile code in exec statements until execution, and won't be able to colour code your code.
People have been suggesting the use of python dictionaries, so I decided to research them. Dictionaries (dict) seem to be a data type similar to lists, except they can be indexed using strings (or other "immutable" data types). Here is a version of my first example that uses a dictionary instead of lists:
Objects={}
def createvtinstance(Object=4,Name="engine1"):
global Objects
Objects[Name]=Object
def Use(Name="engine1"):print(Objects[Name]) # Or: Objects[Name].SomeFunction()
Python seems to have a built in dictionary called globals, which stores all your variables, so you could probably do:
def createvtinstance(Object=4,Name="engine1"):
globals()[Name]=Object # Or globals()[Name]=vtdiagram()
However, this will allow the user to break your program, if they use a name like createvtinstance or tkinter.
I'm writing a python script that takes user input through a GUI and then passes that along to a function that basically reads through text files and checks that what the user requested is there. This function returns an array with True or False for each check.
I want to use this array in a different function (def markup()), but if I call it without giving the function the user input, I get an error.
Is there a way for me to store the results of this function and pass it without needing the user input each time?
Pseudo code:
def clickButton():
userInput = [A,B,C,D,E]
textCheck(userInput)
def textCheck(userInput):
*code for checking text creates an array named allResults*
return allResults
def markup():
results = textCheck()
print(results)
You need to manage allResults as a persistent object. One way is to pass the results everywhere as a parameter, such that whatever thread is executing always has a handle to the list. Another way is to (shudder) make it a global variable -- this is somewhat dangerous as a habit, but may be the easiest for you to implement and maintain. You can also create a Results class and instantiate an object that persists as long as you need it.
I can't recommend one over another without having the flow of the main program.
I ended up calling markup(allResults) at the end of textChecker(). It worked.
I'm currently writing code in Python 2.7, which involves creating an object, in which I have two class methods and other regular methods. I need to use this specific combination of methods because of the larger context of the code I am writing- it's not relevant to this question, so I won't go into depth.
Within my __init__ function, I am creating a Pool (a multiprocessing object). In the creation of that, I call a setup function. This setup function is a #classmethod. I define a few variables in this setup function by using the cls.variablename syntax. As I mentioned, I call this setup function within my init function (inside the Pool creation), so these variables should be getting created, based on what I understand.
Later in my code, I call a few other functions, which eventually leads to me calling another #classmethod within the same object I was talking about earlier (same object as the first #classmethod). Within this #classmethod, I try to access the cls.variables I created in the first #classmethod. However, Python is telling me that my object doesn't have an attribute "cls.variable" (using general names here, obviously my actual names are specific to my code).
ANYWAYS...I realize that's probably pretty confusing. Here's some (very) generalized code example to illustrate the same idea:
class General(object):
def __init__(self, A):
# this is correct syntax based on the resources I'm using,
# so the format of argument isn't the issue, in case anyone
# initially thinks that's the issue
self.pool = Pool(processes = 4, initializer=self._setup, initargs= (A, )
#classmethod
def _setup(cls, A):
cls.A = A
#leaving out other functions here that are NOT class methods, just regular methods
#classmethod
def get_results(cls):
print cls.A
The error I'm getting when I get to the equivalent of the print cls.A line is this:
AttributeError: type object 'General' has no attribute 'A'
edit to show usage of this code:
The way I'm calling this in my code is as such:
G = General(5)
G.get_results()
So, I'm creating an instance of the object (in which I create the Pool, which calls the setup function), and then calling get_results.
What am I doing wrong?
The reason General.A does not get defined in the main process is that multiprocessing.Pool only runs General._setup in the subprocesses. This means that it will not be called in the main process (where you call Pool).
You end up with 4 processes where in each of them there is General.A is defined, but not in the main process. You don't actually initialize a Pool like that (see this answer to the question How to use initializer to set up my multiprocess pool?)
You want an Object Pool which is not natively impemented in Python. There's a Python Implementation of the Object Pool Design Pattern question here on StackOverflow, but you can find a bunch by just searching online.