Python: Dynamically define functions of a class - python

I want to create a function in a class that sequently runs a number of functions. But what functions are executed should depend on conditions, for example a function that could write results to the disk or to a database or to both of that. But with millions of calculations I dont want a if statement that asked everytime if the condtion for database or disk writing is True or False in that single function. I wonder what is the best solution for that. I could write some kind of choseFunction(), that fills a list with functions if conditions are True and execute all functions in that list in the writing functions. Or create a Writing Class that only have those functions if they met the condtions and inherit them to the main class as writing function. What is the common way to do such a thing?

import sys
def log(name):
print("running:" + name)
def proc1():
log ( sys._getframe().f_code.co_name)
def proc2():
log ( sys._getframe().f_code.co_name)
def proc3():
log ( sys._getframe().f_code.co_name)
def procA():
log ( sys._getframe().f_code.co_name)
def procB():
log ( sys._getframe().f_code.co_name)
def procC():
log ( sys._getframe().f_code.co_name)
def setMyFunctions(conditions):
# set your funtions here
option = {
1: [proc1, proc2, proc3],
2: [procA, procB, procC],
};
return option[conditions]
# ready to run as is, just try it
x = True # change the x here to see the inpact
if (x):
status = 1
else:
status = 2
toDoList = setMyFunctions(status)
i = 0; lastTask = len(toDoList)
# log the start
print ( "main started")
while i < lastTask:
# run or deliver your task list here
toDoList[i]()
i += 1
print ( "main finished")

Related

Python class variable is None despite being set

I'm struggling with thread communication in Python. I'm clearly missing something, but I'm new to Python so I don't know very well what I'm doing.
When the server gets a GET request, I want it to get two numbers (x and y coords) from a separate thread, which constantly updates those values and to return those numbers as a response.
I have a simple Django project with the following structure:
it is very basic, made according to tutorial.
When the server starts, I start a thread that looks launches my coordinate generator in a separate thread:
class GpsMockCoordsServiceConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'gps_mock_coords_service'
def ready(self):
if os.environ.get('RUN_MAIN', None) != 'true':
_thread.start_new_thread(CoordsTracker.launch_recognition, ())
CoordsTracker class looks like so:
coords = None
class CoordsTracker:
#coords = None #tried placin it here, but same effect - it is None when retreived from views.py
logger = logging.getLogger("CoordsTrackerLogger")
#staticmethod
def draw_contours(mask, frame, color):
......
for stuff in stuffs:
......
CoordsTracker.set_coords((x, y))
......
#staticmethod
def launch_recognition():
........
while True:
........
CoordsTracker.draw_contours(....)
........
#staticmethod
def set_coords(new_coords):
global coords
CoordsTracker.logger.debug("setting coords " + str(new_coords))
coords = new_coords # here coords var is OK
#staticmethod
def get_coords():
CoordsTracker.logger.debug(coords) # Here it is OK if I call this method from draw_contours() and is not OK if I call this from views.py file.
return coords
views.py class has only this method:
def index(request):
# with CoordsTracker.coords_thread_lock:
coords = CoordsTracker.get_coords()
logger.debug("Got coords: " + str(coords)) #if I do a GET request this prints 'Got coords: None'
return HttpResponse(str(coords))
UPD: after some time debugging with a friend, we found out that it appears that the set_coords() method is called in one process, while get_coords() in another process.
I'd recommend implementing some kind of IPC with the middleware you have. But if it's a one-off project, you can just launch the thread (launch_recognition) from wsgi.py somewhere. This will ensure it all runs in the same process.

How to return values from a scheduled function in python?

I am using Finnhub api to get some live data. I have 2 codes, one which will login the api every once in a day and second one will give the data every hour.
The first function will give details to the second function based on which it will fetch the data.
Here is my first function
def finnhub_login():
finnhub_client = finnhub.Client(api_key="xxxxxxxxxxxx")
symbols = df['SYMBOLS'].to_list()
return symbols,finnhub_client
I would like to use the output i.e symbols and finnhub client to the second function
Here is the second function
def finnhub_api_call(symbols,finnhub_client):
main_value = 0
for i in symbols:
data = finnhub_client.quote(['symbol'])
main_value += data['dp']
return main_value
schedule.every(1).day.do(finnhub_login)
schedule.every(1).hour.do(finnhub_api_call,symbols,finnhub_client)
while True:
schedule.run_pending()
time.sleep(1)
In the above code, how do I save the return values of 1st function and then use it for the second function ?
you can wrap all of this in a class and use class variables.
You can instantiate your class and use the functions from there. Everytime you run the first function class variables will change. Second function will use the class variables instead of function parameters.
class FinnhubCaller:
def __init__(self):
pass
def finnhub_login(self):
self.client = finnhub.Client(api_key="xxxxxxxxxxxx")
self.symbols = df['SYMBOLS'].to_list()
def finnhub_api_call(self):
main_value = 0
for i in self.symbols:
data = self.client.quote(['symbol'])
main_value += data['dp']
return main_value
caller = FinnhubCaller()
schedule.every(1).day.do(caller.finnhub_login)
schedule.every(1).hour.do(caller.finnhub_api_call)
while True:
schedule.run_pending()
time.sleep(1)

Need to delay the item changed signal till my data is loaded

I'm loading a mysql database on a tablewidget.
I have two functions which are connected to the item changed signal in the my QTable Widget. The first makes a list of the changed cells while the second is used to manage the data types input in the table widget cells bringing up an error message if the wrong datatype is put in.
The problem is that the functions work before I load my database in. Effectively storing a list of cells I don't want and popping continuous error messages while it is loading.
How do I halt the functions working till after the database is loaded?
def log_change(self, item):
self.changed_items.append([item.row(),item.column()])
def item_changed(self, Qitem,item):
if (item.column())%2 == 0:
try:
test = float(Qitem.text())
except ValueError:
Msgbox = QMessageBox()
Msgbox.setText("Error, value must be number!")
Msgbox.exec()
Qitem.setText(str(''))
There are 2 options:
Use a flag:
# in constructor
self.is_loading = False
def load_from_db(self):
# in load function
self.is_loading = True
# load from db
# ...
self.is_loading = False
# foo_callback is item_changed by example
def foo_callback(self, arg1, arg2, ...):
if self.is_loading:
return
# do work
Use blockSignals
self.tablewidget.blockSignals(True)
# load from db
# ...
self.tablewidget.blockSignals(False)

Python: Passing an object instance from one function to another?

I'm having trouble with passing a value from one script to another, trying to take it a step at a time but the big picture would be to print the value obj1.get_predval to my Django view and wait for the users' input.
active_learner.obj1.get_predval in my beta.py script doesn't work, it just prints out the initial value which makes sense because it's not running the main.py but I'm not sure how I'd pass the value of obj1.set_predval(machine_prediction) from main.py. It properly outputs the obj1.get_predval in the main.py script.
I'm assuming I have a fundamental misunderstanding, for now, all I'm trying to return is the value of obj1.get_predval in function beta.py, when it gets to the line return value and wait for user input then continue.
main.py script below
obj1 = MachinePred()
def main():
model = load_model('model_new.h5')
DATAFILE = "c_user_model_data100000.csv"
dataset = loadtxt(DATAFILE, delimiter=",")
X_pool, Y = dataset[:, 0:5], dataset[:, 5:]
sc_x, sc_y = StandardScaler(), StandardScaler()
X_pool, Y = sc_x.fit_transform(X_pool), sc_y.fit_transform(Y)
learner = ActiveLearner(
estimator = model,
query_strategy = uncertainty_sampling
)
for i in range(3):
query_idx, query_inst = learner.query(X_pool)
print("The machine queried:\n{}\nat index {}".format(
sc_x.inverse_transform(query_inst),
query_idx
)
)
machine_prediction = learner.predict(X_pool[query_idx])
obj1.set_predval(machine_prediction)
print("predvalue:", (obj1.get_predval()))
ratings = []
cc_factor = ["delay", "speed", "missing_words", "paraphrasing"]
for f in cc_factor:
user_answer = input("How would you rate the quality of {} between [1-5]: ".format(f))
ratings.append(user_answer)
print(ratings, np.array([ratings]).reshape(1,-1))
if __name__ == '__main__':
main()
beta.py
This is the script I'm trying to pass the value to below
import active_learner
print(A is: ", active_learner.obj1.get_predval)
mac.py Simple python script using the get and set methods below.
class MachinePred:
predval = 0 # Default value of the 'x' configuration setting
def __init__(self):
self.predval = 0
def set_predval(self, val):
self.predval = val
def get_predval(self):
return self.predval
So the solution to this was very simple, from my understanding it could be done using generator-based coroutines or splitting it into two functions inside a class and use an OO design. The coroutine method would use"yield" which would force exit the function returning the value then re-enter the function but this would limit your ability to use non-generator based coroutines which I did need to await input from my front end.
Using a class though you could put the active learner model and data in an "init method" then split from the machine_prediction = learner.predict(X_pool[query_idx]) for the first function after returning the values and perform the rest in a second function.

Timed Threaded function as an attribute in a class

So I am making a text based adventure game. I am working on the engine right now and I am stuck after long hours searching for a solution for this problem.
I have a class called use_action. One of the arguments for that class is a name of a function. I would like to be able to create this action and have a possible custom function incase the item that calls this use_action does something specific.
The custom function I am working with right now is where the player is hurt and is losing 5 HP every so many seconds.
This should start when he uses a specific item and then stops when he uses the medicine that will link to the stop function. The problem I have is that the function gets called immediately. Even though I am trying to call it at the end of a long if else statement. And then when i get to where i am trying to call it it doesn't call.
I am not posting the whole class as it along with its functions are about 150 lines of code.
class use_action(object):
def __init__(self, function = None):
self.function = function
pizza_act = use_action(function = mechanics.tmr.start())
#This is located at the end of an if else statement after the player types use . . .
if self.function != None:
self.function
else:
pass
From Mechanics:
thread_list = []
class TimerClass(threading.Thread):
def __init__(self, function, time):
threading.Thread.__init__(self)
self.event = threading.Event()
self.function = function
self.time = time
thread_list.append(self)
def run(self):
while not self.event.is_set():
self.event.wait( self.time )
self.function()
def stop(self):
self.event.set()
def blank_current_readline():
# Next line said to be reasonably portable for various Unixes
(rows,cols) = struct.unpack('hh', fcntl.ioctl(sys.stdout, termios.TIOCGWINSZ,'1234'))
text_len = len(readline.get_line_buffer())+2
# ANSI escape sequences (All VT100 except ESC[0G)
sys.stdout.write('\x1b[2K') # Clear current line
sys.stdout.write('\x1b[1A\x1b[2K'*(text_len/cols)) # Move cursor up and clear line
sys.stdout.write('\x1b[0G') # Move to start of line
def pizza_poisoned_action():
# threading.Timer(10, pizza_poisoned_action).start()
blank_current_readline()
print "You lost 5 hp."
initialization.gamer.hp -= 5
sys.stdout.write('> ' + readline.get_line_buffer())
sys.stdout.flush() # Needed or text doesn't show until a key is pressed
tmr = TimerClass(pizza_poisoned_action, 5)
Sorry about the length, I tried to only post the relevant stuff for this. If you think i should post some other piece of code that may be relevant let me know!
If you want to pass a function, don't call it. Or else, you'll be passing the return value.
pizza_act = use_action(function = mechanics.test()) #Wrong!
pizza_act = use_action(function = mechanics.test) #Right

Categories