Python class variable is None despite being set - python

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.

Related

How to get the clock arguement of event.post(clock, data, duration) in a python device?

I cannot find an example in the Simics documentation on how the clock object is obtained so that we can use it as an argument in the post() method.
I suspect that either
an attribute can be used to get the clock or
in the ConfObject class scope we get the clock using SIM_object_clock()
I created a new module using bin\project-setup --py-device event-py
I have defined two methods in the ConfObject class scope called clock_set and clock_get.
I wanted to use these methods so that I can set/get the clock object to use in the post method.
The post() method fails when reading the device registers in the vacuum machine.
import pyobj
# Tie code to specific API, simplifying upgrade to new major version
import simics_6_api as simics
class event_py(pyobj.ConfObject):
"""This is the long-winded documentation for this Simics class.
It can be as long as you want."""
_class_desc = "one-line doc for the class"
_do_not_init = object()
def _initialize(self):
super()._initialize()
def _info(self):
return []
def _status(self):
return [("Registers", [("value", self.value.val)])]
def getter(self):
return self
# In my mind, clock_set is supposed to set the clock object. That way we can use
# it in post()
def clock_set(self):
self.clock = simics.SIM_object_clock(self)
def clock_get(self):
return self.clock(self):
class value(pyobj.SimpleAttribute(0, 'i')):
"""The <i>value</i> register."""
class ev1(pyobj.Event):
def callback(self, data):
return 'ev1 with %s' % data
class regs(pyobj.Port):
class io_memory(pyobj.Interface):
def operation(self, mop, info):
offset = (simics.SIM_get_mem_op_physical_address(mop)
+ info.start - info.base)
size = simics.SIM_get_mem_op_size(mop)
if offset == 0x00 and size == 1:
if simics.SIM_mem_op_is_read(mop):
val = self._up._up.value.val
simics.SIM_set_mem_op_value_le(mop, val)
# POST HERE AS TEST self._up._up.ev1.post(clock, val, seconds = 1)
else:
val = simics.SIM_get_mem_op_value_le(mop)
self._up._up.value.val = val
return simics.Sim_PE_No_Exception
else:
return simics.Sim_PE_IO_Error
You mention using the vacuum example machine and within its script you see that sdp->queue will point to timer. So SIM_object_clock(sdp) would return timer.
Simics is using queue attribute in all conf-objects to reference their clock individually, though other implementations are used too.
BR
Simon
#IAmIntel

OTree / Django send player to results/ exit page if StringField input not in my dict

I’m working with OTree with self: https://otree.readthedocs.io/en/self/
On the first page of my experiment, I ask the players to provide an access code / their matriculation number via StringField. If their input is not in my dict in Constants, I want to send them directly to a page where I tell them „Sorry, you can’t participate“ with the only option for them to click the next button and exit the experiment.
I have tried the following:
in models.py
class Constants(BaseConstants):
name_in_url = 'prisoners_test1'
players_per_group = 2
num_rounds = 1
matriculation_dict = {
'123': ('Adam Smith', 'Economics'),
'124': ('Ada Lovelace', 'Programming'),
'125': ('Charles Babbage', 'Mathematics'),
}
class Player(BasePlayer):
matriculation = models.StringField(label='Please provide your Matriculation Number')
access = models.BooleanField()
def matriculation_not_found(self):
if self.matriculation in Constants.matriculation_dict:
self.access = True
else: self.access = False
in pages.py
class ExcludedPlayer(Page):
def is_displayed(self):
return self.player.access == False
page_sequence = [Matriculation, ExcludedPlayer, P1_Decision, P2_Decision, ResultsWaitPage, Results]
The problem is that the value of access is not updated through my if statement.
My second problem is that even if the page ExcludedPlayer is displayed (b/c I set initial value of access = False), the player is directed to the other pages (P1_Decision, ResultsWaitPage, Results) after clicking next. How can I end the game for the excluded player?
Thank you for your help!
To your first problem:
To update the access field, you need to call your matriculation_not_found method somewhere. A good place for this is the otree built-in method before_next_page in your Matriculation class:
class Matriculation(Page):
def before_next_page(self):
self.player.matriculation_not_found()
Or in newer otree versions (no-self format):
class Matriculation(Page):
#staticmethod
def before_next_page(player, timeout_happened):
player.matriculation_not_found()
To your second problem:
The easiest way to prevent the excluded players from seeing the upcoming pages is to remove the next-button. Simply delete the following line from the ExcludedPlayer.html template:
{{ next_button }}
If for some reason you don't want that, you can also check on each of the upcoming pages in the is_displayed method whether access is allowed or not. For example for the P1_Decision page:
class P1_Decision(Page):
def is_displayed(self):
return self.player.access
And again the same in the new no-self format:
class P1_Decision(Page):
#staticmethod
def is_displayed(player):
return player.access
Another alternative would be to swap out the ExcludedPlayers page to a later app (let's call it 'exculuded_players_app') and skip the pages (and apps) in between using the app_after_this_page method:
class Matriculation(Page):
def before_next_page(self):
self.player.matriculation_not_found()
def app_after_this_page(self, upcoming_apps):
if not self.player.access:
return 'exculuded_players_app'
And again the same in the new no-self format:
class Matriculation(Page):
#staticmethod
def before_next_page(player, timeout_happened):
player.matriculation_not_found()
#staticmethod
def app_after_this_page(player, upcoming_apps):
if not player.access:
return 'exculuded_players_app'

How can I use an 'update' function to 'open' and update if the object is not yet open?

My example is a progress bar
In its simplest form a progress bar is
bar = ProgressBar.Open()
for item in list:
bar.Update(count, len(list))
I would instead like my calling code to be
for item in list:
bar.Update(count, len(list))
I want my Update() function to Open() a bar for the caller if one is not open. The caller doesn't need any other access to the bar than to update it so there's no value in having the meter` handle.
How can I retain state to tell if the Update had been previously called?
I could create a global variable and keep track that way, but I have a gut sense there's a Pythonista way of doing it.
Trying again, but in a way that has no application to stumble on.
The base question is:
I have a function that will be called multiple times.
I want to do something different the first time it is called.
How can a function in Python do that?
In C, that of course would be a...
static variable
I'm just now kinda figuring it out as I type, sorry.
========================
I'm sure all these edits are not how stackoverflow is supposed to work. I'm sorry for not getting it right yet, but am very appreciative of the replies.
Despite it sounding like I'm breaking all the rules of good practices, it's when looked at from the CALLER'S point of view that I had hoped to make an impact.
What if the only thing you needed to do to add a progress meter, even for debugging, to your program was make a call to a progress meter update in the location you want to show progress?
That's the underlying motivation. Slide in 1-line, get something cool for the trouble.
This progress meter was added to my otherwise boring file de-duplicator by adding just the single call:
msg = f'Deduplicating {idx} of {total_files} files\n' f'{dup_count} Dupes found\n' f'{small_count} Too small'
not_cancelled = sGUI.ProgressBar('De-dupe', msg, idx, total_files)
To avoid using global variables, you can use decorator. Here's a simple example:
def open():
print 'open'
def update():
print 'update'
def call_once(func1, *args1, **kwargs1):
def decorator(func2):
called = [False]
def wrapper(*args2 ,**kwargs2):
if not called[0]:
func1(*args1, **kwargs1)
called[0] = True
return func2(*args2, **kwargs2)
return wrapper
return decorator
#call_once(open)
def my_update():
update()
for i in xrange(5):
my_update()
which give the result:
open
update
update
update
update
update
For more information about decorator, please visit: https://wiki.python.org/moin/PythonDecorators
For what you want, you can use a class:
class ProgressBar:
def __init__(self):
self._opened = False
def Open(self):
print("Open")
def Update(self):
if self._opened:
print("Update!")
else:
self.Open()
print("set flag")
self._opened = True
print("Update")
In action:
In [32]: bar = ProgressBar()
In [33]: bar.Update()
Open
set flag
Update
In [34]: bar.Update()
Update!
Note: I copied your casing so as to make it more clear to you, however, the official Python style would be like this:
class ProgressBar:
def __init__(self):
self._opened = False
def open(self):
pass # open stuff
def update(self):
if self._opened:
pass # update stuff
else:
self.open()
self._opened = True
Using snake_case for everything except the ClassName.
OK, I found a solution using 'globals'. I thought that a nested function was the way to do it... then I mixed the two.
By 'globals' I meant variables declared outside the scope of a function. I want to be able to import my module without the import creating anything.
Here's the code that shows how to do this with globals
def my_update(amount):
global flag
if 'flag' in globals():
print('I have been here')
else:
print('I have not been here')
flag = True
return
for i in range(10):
print(f'Calling number {i}')
result = my_update(1)
It does the job for the goals I had set out, but I'm SURE there are better, safer ways that are more elegant as well.
I posted this question on a Python forum and got back the best answer so far using a function attribute. It's brilliant and it works.
Here is code that demonstrates this construct... it should go in everyone's 'Favorite Python Constructs' notebook in my opinion.
def func():
if not hasattr(func, 'static_variable'):
func.static_variable = 0
func.static_variable += 1
return func.static_variable
def main():
for i in range(10):
print('func = {}'.format(func()))
if __name__ == '__main__':
main()
The output is
func = 1
func = 2
func = 3
func = 4
func = 5
func = 6
func = 7
func = 8
func = 9
func = 10

NameError in python unittest

I am trying to test a python method of a file-A which uses a variable in file-A.
My file-A method looks like this:
def rotate(self, rotation):
self.current_face = board.positions[(board.positions.index(self.current_face) + rotation) % 4]
Note: This is inside class A-1 in file-A
The main for file-A looks like this:
if __name__ == '__main__':
inp = Input("input.txt") # create Input object
board = Board(inp.lines[0]) # create board object -----> NOTE
rover_objects(inp.lines[1:]) # create rover objects
process_and_print() # process and print output
So, when I run file-A, it works exactly like I want it to work.
Now, I am trying to test def rotate(self, rotation) in file-A
My test code looks like:
class RoverTest(unittest.TestCase):
def setUp(self):
description = '1 2 N'
moves = 'LMLMLMLMM'
self.testRover = Rover(description, moves)
def test_coordinates(self):
self.testRover.rotate(rotation = 4) -----> Problem
self.assertEqual(self.testRover.current_face, 'N')
The issue is, rotate method in file-A uses the object board in the main in file-A
I am not sure how to pass board to the rotate function from the test.
If I run my test right now, I am thrown an error:
NameError: name 'board' is not defined
How can I fix this error?
If you are writing a class that depends on other classes existing, you should make it accept those dependencies as arguments to the initialisation, rather than just hoping they are defined globally. For example:
class A1(object):
def __init__(self, inputfile):
self.inp = Input(inputfile)
self.board = Board(self.inp.lines[0])
def rotate(self, rotation):
self.current_face = self.board.positions[(self.board.positions.index(self.current_face) + rotation) % 4]
Now in both your main and test files you can instantiate A1 directly by passing the input file.
This is just an example of course; you might want to instantiate the Board object outside the class and pass it in directly. Either way is fine, the important part is that you're passing in any dependencies.

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