what thread-synch mech to use for clean exit from a thread

G

Gildor Oronar

A currency exchange thread updates exchange rate once a minute. If the
thread faield to update currency rate for 5 hours, it should inform
main() for a clean exit. This has to be done gracefully, because main()
could be doing something delicate.

I, a newbie, read all the thread sync tool, and wasn't sure which one to
use. In fact I am not sure if there is a need of thread sync, because
there is no racing cond. I thought of this naive way:

class CurrencyExchange():
def __init__(in_case_callback):
this.callback = in_case_callback
def __run__():
while time.time() - self.rate_timestamp < 5*3600:
... # update exchange rate
if success:
self.rate_timestamp == time.time()
time.sleep(60)
this.callback() # rate not updated 5 hours, a crisis

def main():
def callback()
Go_On = False

agio = CurrencyExchange(in_case = callback)
agio.start()

Go_On = True
while Go_On:
do_something_delicate(rate_supplied_by=agio)

As you can see, if there is no update of currency rate for 5 hours, the
CurrencyExchange object calls the callback, which prevents main() from
doing the next delicate_thing, but do not interrupt the current
delicate_thing.

This seems OK, but doesn't look pythonic -- replacing callback() with a
lambda doesn't help much, it still look naive. What is the professional
way in this case?

Thanks in advance!
 
Z

zhangweiwu

What is the professional way in this case?

Hi. I am not a professional neither but I think a professional does this:

class CurrencyExchange():
def __init__(in_case_callback):
this.callback = in_case_callback
def __run__():
while time.time() - self.rate_timestamp < 5*3600:
... # update exchange rate
if success:
self.rate_timestamp == time.time()
time.sleep(60)

def main():

agio = CurrencyExchange(in_case = callback)
agio.start()
while agio.is_alive():
do_something_delicate(rate_supplied_by=agio)

Notice even if agio is no longer alive, it can still supply exchange rate for the last delicate_thing, only that it no longer updates punctually. Thisis semantic wrong, and I think it is the fault of python: how can something dead execute its method? In the API, thread.is_alive() should be renamed to thread.is_activate_and_on_his_own()
 
S

Steven D'Aprano

A currency exchange thread updates exchange rate once a minute. If the
thread faield to update currency rate for 5 hours, it should inform
main() for a clean exit. This has to be done gracefully, because main()
could be doing something delicate.

I, a newbie, read all the thread sync tool, and wasn't sure which one to
use. In fact I am not sure if there is a need of thread sync, because
there is no racing cond. I thought of this naive way:

class CurrencyExchange():
def __init__(in_case_callback):
this.callback = in_case_callback

You need to declare the instance parameter, which is conventionally
called "self" not "this". Also, your class needs to inherit from Thread,
and critically it MUST call the superclass __init__.

So:

class CurrencyExchange(threading.Thread):
def __init__(self, in_case_callback):
super(CurrencyExchange, self).__init__()
self.callback = in_case_callback

But I'm not sure that a callback is the right approach here. See below.

def __run__():

Likewise, you need a "self" parameter.

while time.time() - self.rate_timestamp < 5*3600:
... # update exchange rate
if success:
self.rate_timestamp == time.time()
time.sleep(60)
this.callback() # rate not updated 5 hours, a crisis

I think that a cleaner way is to just set a flag on the thread instance.
Initiate it with:

self.updates_seen = True

in the __init__ method, and then add this after the while loop:

self.updates_seen = False


def main():
def callback()
Go_On = False

I don't believe this callback will work, because it will simply create a
local variable call "Go_On", not change the non-local variable.

In Python 3, you can use the nonlocal keyword to get what you want, but I
think a better approach is with a flag on the thread.
agio = CurrencyExchange(in_case = callback)
agio.start()

Go_On = True
while Go_On:
do_something_delicate(rate_supplied_by=agio)

Change to:

while agio.updates_seen:
do_something_delicate...
 
S

Steven D'Aprano

Oh, I forgot another comment...

I think that a cleaner way is to just set a flag on the thread instance.
Initiate it with:

self.updates_seen = True

in the __init__ method, and then add this after the while loop:

self.updates_seen = False

Sorry, I forgot to mention... I assume that the intention is that if the
thread hasn't seen any updates for five hours, it should set the flag,
and then *keep going*. Perhaps the rate will start updating again later.

If the intention is to actually close the thread, then there's no reason
for an extra flag. Just exit the run() method normally, the thread will
die, and you can check the thread's status with the is_alive() method.
 
M

MRAB

You need to declare the instance parameter, which is conventionally
called "self" not "this". Also, your class needs to inherit from Thread,
and critically it MUST call the superclass __init__.

So:

class CurrencyExchange(threading.Thread):
def __init__(self, in_case_callback):
super(CurrencyExchange, self).__init__()
self.callback = in_case_callback

But I'm not sure that a callback is the right approach here. See below.



Likewise, you need a "self" parameter.

The "==" in this line should, of course, be "=":
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top