Calling a Function from Within a Class - python

If I have a case where I have a simple logging function in my main file:
def log_events(data_to_log):
log_this = '%s - %s' % (strftime("%Y-%m-%d %H:%M:%S"), data_to_log)
print ('%s\r' % log_this[0:140])
hlog_file = open('%s' % LOG_FILE_NAME, 'a')
print ( log_this, file=hlog_file)
hlog_file.close()
I have different classes for different tasks. I want to reuse the same log function in every class i make. This is in a file called. doit.py
class DoStuff:
def __init__ (self, extra_stuff_):
self.some_extra_stuff = extra_stuff
def do_the_thing(self):
x = 1
log_events( ' x is currently %s' % x )
x = 2
log_events( ' x is currently %s' % x )
log_events( ' extra stuff is %s' % self.some_extra_stuff )
Now the final code:
import doit
def log_events(data_to_log):
log_this = '%s - %s' % (strftime("%Y-%m-%d %H:%M:%S"), data_to_log)
print ('%s\r' % log_this[0:140])
hlog_file = open('%s' % LOG_FILE_NAME, 'a')
print ( log_this, file=hlog_file)
hlog_file.close()
things_i_want_to_do = doit.DoStuff('this is the stuff')
things_i_want_to_do.do_the_thing()
I get:
NameError: name 'log_events' is not defined
Is there a better way of sharing that log_events function with all the imported classes?

Related

How to print the name and value of a variable?

This is what I have in mind because I find myself typing the name twice whenever I want to inspect the value of a variable:
a = 1
my_print(a) # "a: 1"
Is this possible in Python?
If you are in control of the calling function, you can hack this to work reasonably well like:
Code:
import inspect
def print_name_and_value(var):
lines = inspect.stack()[1][4]
var_name = ''.join(lines).strip().split('(')[-1].split(')')[0]
print("%s: %d" % (var_name, var))
a = 5
print_name_and_value(a)
Results:
a: 5
How does this work?
The inspect module can be used to inspect the caller, and get the line of code used by the caller. With a bit of string hacking the variable name (assuming it is a simple variable and not a more complex expression) can be gathered from the source code.
I would say "no", and any other magic doable is just... too much magic.
However there's something you can do, and that's looking at the stack trace using the inspect module.
import inspect
def my_print(thingy):
# print("id(thingy)=%s" % id(thingy))
previous_frame = inspect.currentframe().f_back
# print("locals: %s" % previous_frame.f_locals)
for variable_name, variable_value in previous_frame.f_locals.items():
if id(variable_value) == id(thingy):
return("%s: %s" % (variable_name, variable_value))
# print("globals: %s" % previous_frame.f_globals)
for variable_name, variable_value in previous_frame.f_globals.items():
if id(variable_value) == id(thingy):
return("%s: %s" % (variable_name, variable_value))
if __name__ == '__main__':
a = 1
print("Test %s" % my_print(a)) # "a: 1"
list_thingy = [1, 2, 3]
print("Test %s" % my_print(list_thingy))
def and_within_function():
d = {1: "a"}
print("Test %s" % my_print(d))
and_within_function()
But this is not reliable and I'd use it more as a curiosity, since there are plenty of "special cases". For instance: the first 255 integers (I think) in Python occupy a specific memory address so, if you have two variables that are =1 I don't think you're gonna really be guaranteed which one is it.

AttributeError: 'Rules' object has no attribute '_Rules__temperature'

I have a program that is aiming to take inputs from sensors and then act upon inputs from these sensors from some pre-defined rules that are stored and called within a class. I am having problems passing the variables that the sensors are defined as into the rules class. Where I get errors of 'Rules object has not attribute .rules_temperature. My code is below:
class myInterfaceKit():
__interfaceKit = None
def __init__(self ):
try:
self.__interfaceKit = InterfaceKit()
except RuntimeError as e:
print("Runtime Exception: %s" % e.details)
print("Exiting....")
exit(1)
def open(self):
try:
self.__interfaceKit.openPhidget()
except PhidgetException as e:
print("Phidget Exception %i: %s" % (e.code, e.details))
def getInterfaceKit(self):
return self.__interfaceKit
def getSensor(self, sensor):
return self.__interfaceKit.getSensorValue(sensor)
class sensors():
__sound = 0
__temperature = 0
__light = 0
__motion = 0
__dbName = ""
__interfaceKit = None
__connection = None
__rules = None
def __init__(self, theInterfaceKit, dbName):
self.__sound = 0
self.__temperature=0
self.__light=0
self.__motion=0
self.__timeStamp=time.time()
self.__strTimeStamp=datetime.datetime.fromtimestamp(self.__timeStamp).strftime('%Y-%m-%d %H:%M:%S')
self.__dbName = dbName
self.__interfaceKit = theInterfaceKit
self.__connection = sqlite3.connect('testing1.db', check_same_thread=False) ######
def interfaceKitAttached(self, e):
attached = e.device
print("InterfaceKit %i Attached!" % (attached.getSerialNum()))
self.__interfaceKit.getInterfaceKit().setSensorChangeTrigger(0, 5)
self.__interfaceKit.getInterfaceKit().setSensorChangeTrigger(1, 35)
self.__interfaceKit.getInterfaceKit().setSensorChangeTrigger(2, 60)
self.__interfaceKit.getInterfaceKit().setSensorChangeTrigger(3, 200)
def sensorInputs(self, e):
temperature = (self.__interfaceKit.getSensor(0)*0.2222 - 61.111)
sound = (16.801 * math.log((self.__interfaceKit.getSensor(1))+ 9.872))
light = (self.__interfaceKit.getSensor(2))
motion = (self.__interfaceKit.getSensor(3))
# check temperature has changed - if yes, save and update
if temperature != self.__temperature:
self.__timeStamp=time.time()
self.__strTimeStamp=datetime.datetime.fromtimestamp(self.__timeStamp).strftime('%Y-%m-%d %H:%M:%S')
self.__temperature = temperature
print("Temperature is: %i:" % self.__temperature)
self.writeToDatabase( 'temperature', self.__temperature, self.__strTimeStamp)
#check sound has changed - if yes, save and update
if sound != self.__sound:
self.__timeStamp=time.time()
self.__strTimeStamp=datetime.datetime.fromtimestamp(self.__timeStamp).strftime('%Y-%m-%d %H:%M:%S')
self.__sound = sound
print("Sound is: %i " % self.__sound)
self.writeToDatabase( 'sound', self.__sound, self.__strTimeStamp )
#check light has changed - if yes, save and update
if light != self.__light:
self.__timeStamp=time.time()
self.__strTimeStamp=datetime.datetime.fromtimestamp(self.__timeStamp).strftime('%Y-%m-%d %H:%M:%S')
self.__light = light
print("Light is: %i " % self.__light)
self.writeToDatabase( 'light', self.__light, self.__strTimeStamp )
if motion != self.__motion:
self.__motion = motion
print ("motion is %i" % self.__motion)
def openDatabase(self):
cursor = self.__connection.cursor()
cursor.execute("CREATE TABLE " + self.__dbName + " (sensor text, value text, time_stamp text)")
def writeToDatabase(self, sensorType, data, time):
cursor = self.__connection.cursor()
cursor.execute("INSERT INTO " + self.__dbName + " VALUES (?, ?, ?)", (sensorType, data, time))
self.__connection.commit()
def closeDatabase():
self.__connection.close()
def start(self):
try:
self.__interfaceKit.getInterfaceKit().setOnAttachHandler(self.interfaceKitAttached)
self.__interfaceKit.getInterfaceKit().setOnSensorChangeHandler(self.sensorInputs)
self.openDatabase()
except PhidgetException as e:
print("Phidget Exception %i: %s" % (e.code, e.details))
print("Exiting....")
exit(1)
This is where the problem lies:::
class Rules(sensors):
__tempLower=0
__tempUpper=0
def __init__(self):
self.__tempLower=28
self.__tempUpper=30
self.__temperature
def tempRule(self, sensors): ##Temperature rule
if self.__temperature == self.__tempLower:
print("testing")
phidgetInterface = myInterfaceKit()
phidgetInterface.open()
theSensors = sensors(phidgetInterface, "event156")
theSensors.start()
theRule = Rules()
theRule.tempRule()
chr = sys.stdin.read(1)
edit, error message:
Traceback (most recent call last):
File "H:\Project\Student\Prototype 1\eventProto.py", line 159, in
theRule = Rules()
File "H:\Project\Student\Prototype 1\eventProto.py", line 146, in init
self.__temperature
AttributeError: 'Rules' object has no attribute 'Rules_temperature'
Private members (starting with __) cannot be accessed by subclasses. (Well, they can be accessed using some hackery, but should not).
(see here)
In your case, __temperature is a private member of the base class sensors, but you're accessing it from the subclass Rules.
Replace the double underscore prefix with a single underscore (__temperature -> _temperature), and you're good to go.
Double underscore members are considered private, you have to prepend those with class name that defined said member.
Use these magic private members like this:
class sensors:
__temp = 42
assert sensors()._sensors__temp == 42
class Rules(sensors):
def test(self):
assert self._sensors__temp == 42
Rules().test()

Python missing attributes/attributes not valid

This is the code I am running but it says "These attributes are not valid", how do I list attributes/transforms in my scene so I can list them properly. I tried using cmds.ls(type='transform') but it still doesn't work. Any help is appreciated.
import maya.cmds as cmds
def changeXtransformVal(myList, percentage=2.0):
"""
Changes the value of each transform in the scene by a percentange.
Parameters:
percentage - Percentange to change each transform's value. Default value is 1.
Returns:
Nothing.
"""
# The ls command is the list command. It is used to list various nodes
# in the current scene. You can also use it to list selected nodes.
transformInScene = cmds.ls(type='transform')
found = False
for thisTransform in transformInScene:
if thisTransform not in ['front','persp','side','top']:
found = True
break
else:
found = False
if found == False:
sphere1 = cmds.polySphere()[0]
cmds.xform(sphere1, t = (0.5, 0.5, 0.5))
transformInScene = cmds.ls(type='transform')
# If there are no transforms in the scene, there is no point running this script
if not transformInScene:
raise RuntimeError, 'There are no transforms in the scene!'
badAttrs = list()
# Loop through each transform
for thisTransform in transformInScene:
if thisTransform not in ['front','persp','side','top']:
allAttrs = cmds.listAttr(thisTransform, keyable=True, scalar=True)
allAttrs = [ i for i in badAttrs if i != "visibility" ]
print allAttrs
for attr in myList:
if attr in allAttrs:
currentVal = cmds.getAttr( thisTransform + "." + attr )
newVal = currentVal * percentage
cmds.setAttr(thisTransform + "." + attr, newval)
print "Changed %s. %s from %s to %s" % (thisTransform,attr,currentVal,newVal)
else:
badAttrs.append(attr)
if badAttrs:
print "These attributes %s are not valid" % str()
myList = ['sx', 'sy', 'tz', 'ty', 'tx']
changeXtransformVal(myList, percentage=2.0)
You have a simple indentation error in several places. The last (on line 35):
for attr in myList:
the code is a level too low. The code on line 31 > :
if thisTransform not in ['front','persp','side','top']:
allAttrs = cmds.listAttr(thisTransform, keyable=True, scalar=True)
Should all be on the if level. Also this makes no sense:
allAttrs = [ i for i in badAttrs if i != "visibility" ]
is indented wrong all your code after that should be on the level of your if. Here's the central part written again:
import maya.cmds as cmds
def changeXtransformVal(myList, percentage=2.0):
transformInScene = [i for i in cmds.ls(type='transform') if i not in ['front','persp','side','top'] ]
myList = [i for i in myList if i not in ['v','visibility']]
for thisTransform in transformInScene:
badAttrs = []
for attr in myList:
try:
currentVal = cmds.getAttr( thisTransform + "." + attr )
newVal = currentVal * percentage
cmds.setAttr(thisTransform + "." + attr, newVal)
print "Changed %s. %s from %s to %s" % (thisTransform,attr,currentVal,newVal)
except TypeError:
badAttrs.append(attr)
if badAttrs:
print "These attributes %s are not valid" % str(badAttrs)
myList = ['sx', 'sy', 'tz', 'ty', 'tx']
changeXtransformVal(myList, percentage=2.0)
Note the nesting is a bit too deep consider moving the looping of mattress into a function definition.

python object in dictionary

I am trying to save the object candle in the dictionary candlebuffer, however it gives me the error below. I am struggling; what is incorrect with my syntax?
class Observer:
def __init__(self):
self.listeners = []
def attach(self, listener):
if not listener in self.listeners:
self.listeners.append(listener)
def notify(self, event):
for listener in self.listeners:
listener.update(event)
class CandleGenerator(Observer):
def __init__(self,freq):
Observer.__init__(self)
self.freq = freq
self.candle = Candle()
def update(self,tick):
self.candle.addTick(tick,self.freq)
if keyfunc(self.candle.timestamp,self.freq) != self.candle.ref_timestamp:
self.notify(self.candle)
self.candle = Candle()
class CandlePrinter:
def update(self, candle):
print "Bougie>>>>>> freq: %s %s %s %s %s %s %s %s %s " % (candle.freq,candle.last_price,candle.volume, candle.timestamp, candle.ref_timestamp, candle.open_price,candle.high_price,candle.low_price, candle.last_price)
class CandleBuffer:
def __init__(self,candle):
self.candlebuffer={0: candle}
def update(self,candle):
self.candlebuffer[candle.timestamp]= candle
print self.candlebuffer
print('begin')
tickGenerator = TickGenerator()
candleGenerator1 = CandleGenerator(1)
candlePrinter = CandlePrinter()
candleBuffer = CandleBuffer(5)
tickGenerator.attach(candleGenerator1)
candleGenerator1.attach(candlePrinter)
candleGenerator1.attach(candleBuffer)
tickGenerator.generate()
It gives the following output:
TypeError: __init__() takes exactly 2 arguments (1 given)
Since you have confirmed what I was suspecting, you have to pass another argument to the constructor, and use a dictionary instead of a set:
class CandleBuffer():
def __init__(self,candle):
self.candlebuffer={0 : candle}
def update(self,candle):
self.candlebuffer[candle.timestamp]= candle
# ...
candleBuffer = CandleBuffer(a_candle)
candleBuffer.update(another_candle)
This isn't what cause your error but you need to use : to create a dictionary.
self.candlebuffer = { 0 : candle }
It's on the format key : value.
I guessing that you're creating a CandleBuffer without giving an argument somewhere else in your code.

Python Unit Testing a loop function

This is a followup question from 1
I need to test the function with two given cases in a loop. However, based on the printed results, it seems like only the first iteration is checked? Is this related to runner.run(unittest.makeSuite(MyTestCase))?
import unittest
from StringIO import StringIO
import rice_output
class MyTestCase(unittest.TestCase):
def setUp(self):
#####Pre-defined inputs########
self.dsed_in=[1,2]
self.a_in=[2,3]
self.pb_in=[3,4]
#####Pre-defined outputs########
self.msed_out=[6,24]
#####TestCase run variables########
self.tot_iter=len(self.a_in)
def testMsed(self):
for i in range(self.tot_iter):
print i
fun = rice_output.msed(self.dsed_in[i],self.a_in[i],self.pb_in[i])
value = self.msed_out[i]
testFailureMessage = "Test of function name: %s iteration: %i expected: %i != calculated: %i" % ("msed",i,value,fun)
return self.assertEqual(round(fun,3),round(self.msed_out[i],3),testFailureMessage)
from pprint import pprint
stream = StringIO()
runner = unittest.TextTestRunner(stream=stream)
result = runner.run(unittest.makeSuite(MyTestCase))
print 'Tests run ', result.testsRun
print 'Errors ', result.errors
Here is he output:
0
Tests run 1
Errors []
[]
Test output
testMsed (__main__.MyTestCase) ... ok
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
Any suggestions? Thanks!
Remove the return statement
def testMsed(self):
for i in range(self.tot_iter):
print i
fun = rice_output.msed(self.dsed_in[i],self.a_in[i],self.pb_in[i])
value = self.msed_out[i]
testFailureMessage = "Test of function name: %s iteration: %i expected: %i != calculated: %i" % ("msed",i,value,fun)
self.assertEqual(round(fun,3),round(self.msed_out[i],3),testFailureMessage)

Categories