473,396 Members | 1,886 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

yield, curry, mix-in, new.function, global, closure, .... what will work?

Dear list,

maybe I'm overlooking something obvious or this is not possible at all
or I don't know. Please, consider the following code:

## insert here anything you like

def changer():
change_i('changed_i')
change_j('changed_j')

def run(i='', j=''):

## insert here anything you like

return i, j

run() == 'changed_i', 'changed_j'

Let me explain: First, changer() is kind of templating language so it
should be written down in this form - however, it can change during
run-time as you like. Basically, it is just ordinary python code which
changes (should change) the local variables of another function,
run(). Oh, and it has to be *thread-safe*.

Here's what I tried and didn't work (maybe I just haven't tried hard
enough):
- pass i, j around: changer(i, j) and change_i(i, arg) - easiest, most
obvious solution - can't do it, certainly not during writing of the
code - have to preserve changer()'s form
- global variable - not thread-safe
- in run(), create dummy closure for changer() and call it -
new.function(blah, blah, blah, dummy.func_closure) - not thread safe,
i guess, and besides change_i() and change_j() would also need a such
a trick - I am not sure how to alter the codeobject of changer()
- new.function(new.code(... - oh my, this won't work
- in run(), modify change_i() and change_j() so it actually yield-s
the changes, collect them here - something like: change_i.__call__ =
return yield ('changed_i', 'comes_from_changer_i()') - doesn't work,
of course
- update locals() - yes!! - no!! - doen't work, it's just a copy
- curry, mix-in, ... - hmm....
- eval(blah, blah, locals()) - not safe, ugly - maybe? what do you
think?
- find out which file changer() is written in, which line it starts
and ends, read that file's section, parse, edit, append the needed
local variable's declarations, compile to changer_new() and changer =
changer_new - there has to be something better! :)

So, to wrap up, the question is: how can I pass a variable from one
function to another, without writing down function's argument during
coding, and still be thread-safe?

I can only hope you are still with me and not very confused....

Thanks for any feedback!!

Apr 15 '07 #1
8 1873
ec*******@gmail.com writes:
Let me explain: First, changer() is kind of templating language so it
should be written down in this form - however, it can change during
run-time as you like. Basically, it is just ordinary python code which
changes (should change) the local variables of another function,
run(). Oh, and it has to be *thread-safe*.
That is total madness. Just use a normal object or dictionary with a lock.
Apr 15 '07 #2
On Apr 15, 8:07 pm, Paul Rubin <http://phr...@NOSPAM.invalidwrote:
That is total madness. Just use a normal object or dictionary with a lock.
Please, can you elaborate further, I'm not sure if I understood.
Should I lock global variables i, j during the execution of run()? In
that case I have to apologize, I showed rather simplified version of
the actual problem I have - in fact changer() and run() will be a bit
more complex thus executing a bit longer and perhaps causing a dead-
lock.

Apr 16 '07 #3
ec*******@gmail.com writes:
On Apr 15, 8:07 pm, Paul Rubin <http://phr...@NOSPAM.invalidwrote:
That is total madness. Just use a normal object or dictionary with a lock.

Please, can you elaborate further, I'm not sure if I understood.
Should I lock global variables i, j during the execution of run()? In
that case I have to apologize, I showed rather simplified version of
the actual problem I have - in fact changer() and run() will be a bit
more complex thus executing a bit longer and perhaps causing a dead-lock.
Put both variables into one shared object with a lock (see the docs for
threading.RLock()). Acquire the lock before modifying or reading the
variables, and release it afterwards. That is the traditional way.
Another way popular in Python is to have separate threads for changer
and run, and have them communicate through Queue.Queue objects. In no
case should you attempt to write a function that messes with another
function's local variables. Local variables are called "local" for a
reason ;-).

Basically this stuff takes more understanding and getting used to than
I can really convey in a newsgroup post. You might look at some
Wikipedia articles or ASPN recipes about concurrent programming, or
get the Python Cookbook.
Apr 16 '07 #4
On Apr 16, 3:05 am, Paul Rubin <http://phr...@NOSPAM.invalidwrote:
ecir.h...@gmail.com writes:
Please, can you elaborate further, I'm not sure if I understood.
Should I lock global variables i, j during the execution of run()? In
that case I have to apologize, I showed rather simplified version of
the actual problem I have - in fact changer() and run() will be a bit
more complex thus executing a bit longer and perhaps causing a dead-lock.

Put both variables into one shared object with a lock (see the docs for
threading.RLock()). Acquire the lock before modifying or reading the
variables, and release it afterwards. That is the traditional way.
Thanks for the reply! And at the same time, please bear with me.

If I understand correctly: when one thread acquires the lock, every
other thread has to wait. If so, this is not exacly what I would like
to have since the thread might take a bit longer to finish.

The reason why I try so hard to use local variables is that they are
inherently thread-safe. So I don't even mind to copy changer() every
time run() is called - run() has it's own local variables i, j, no one
has to touch them except it's ("local") function changer(). But the
problem is, I don't know how to propagate run()'s variables into
changer() without declarating them as changer()'s arguments (it would
be ok to append the declaration during run-time, though, if I only
knew how).

Apr 16 '07 #5
On Apr 16, 7:28 am, ecir.h...@gmail.com wrote:
On Apr 16, 3:05 am, Paul Rubin <http://phr...@NOSPAM.invalidwrote:
ecir.h...@gmail.com writes:
Please, can you elaborate further, I'm not sure if I understood.
Should I lock global variables i, j during the execution of run()? In
that case I have to apologize, I showed rather simplified version of
the actual problem I have - in fact changer() and run() will be a bit
more complex thus executing a bit longer and perhaps causing a dead-lock.
Put both variables into one shared object with a lock (see the docs for
threading.RLock()). Acquire the lock before modifying or reading the
variables, and release it afterwards. That is the traditional way.

Thanks for the reply! And at the same time, please bear with me.

If I understand correctly: when one thread acquires the lock, every
other thread has to wait. If so, this is not exacly what I would like
to have since the thread might take a bit longer to finish.

The reason why I try so hard to use local variables is that they are
inherently thread-safe. So I don't even mind to copy changer() every
time run() is called - run() has it's own local variables i, j, no one
has to touch them except it's ("local") function changer(). But the
problem is, I don't know how to propagate run()'s variables into
changer() without declarating them as changer()'s arguments (it would
be ok to append the declaration during run-time, though, if I only
knew how).
In Python, names are bound to objects. The parameter names passed to
a function *are not inherently thread safe*! Python parameters are
not passed-by-value. To show you what I mean:
>>spam = ["delicious"]
def test(meal):
.... global spam
.... if spam is meal:
.... print "Spam is the same object as meal"
....
>>test(spam)
Spam is the same object as meal

(While the "global spam" statement is optional in this case, I wanted
to make it painfully obvious where the "spam" name in function test is
coming from.)

It is thread-safe to rebind the name "meal" in the function test (ie,
meal = "Green eggs"). It is not thread-safe to mutate or modify the
object that meal is bound to. In the example given above, appending
data to the list, removing data, changing elements, and other
operations will cause potential race conditions across multiple
threads.

Follow Paul's advice and get acquainted with the issues of concurrent
and threaded programming. Judicious locking will help avoid most race
conditions. If you don't want to keep other threads waiting, make a
copy of your data then release the data lock.

Depending on the data, you can usually have multiple threads "reading"
the data, as long as no other threads write to the data while there
are any readers. A writer can be allowed to change the data, but only
if there are no readers and no other writers. (This is commonly known
as a read/write lock.) I didn't see a read/write lock in the Python
documentation with some casual browsing, but one can be implemented
from the existing thread locking mechanisms.

Your description of what you want to do is rather vague, so I can't
get too specific. You've described how you want to do things, but I
don't know what you're trying to accomplish. Where possible, simplify
your design.

--Jason

Apr 16 '07 #6
On Apr 16, 5:36 pm, "Jason" <tenax.racc...@gmail.comwrote:
On Apr 16, 7:28 am, ecir.h...@gmail.com wrote:
On Apr 16, 3:05 am, Paul Rubin <http://phr...@NOSPAM.invalidwrote:
ecir.h...@gmail.com writes:
Please, can you elaborate further, I'm not sure if I understood.
Should I lock global variables i, j during the execution of run()? In
that case I have to apologize, I showed rather simplified version of
the actual problem I have - in fact changer() and run() will be a bit
more complex thus executing a bit longer and perhaps causing a dead-lock.
Put both variables into one shared object with a lock (see the docs for
threading.RLock()). Acquire the lock before modifying or reading the
variables, and release it afterwards. That is the traditional way.
Thanks for the reply! And at the same time, please bear with me.
If I understand correctly: when one thread acquires the lock, every
other thread has to wait. If so, this is not exacly what I would like
to have since the thread might take a bit longer to finish.
The reason why I try so hard to use local variables is that they are
inherently thread-safe. So I don't even mind to copy changer() every
time run() is called - run() has it's own local variables i, j, no one
has to touch them except it's ("local") function changer(). But the
problem is, I don't know how to propagate run()'s variables into
changer() without declarating them as changer()'s arguments (it would
be ok to append the declaration during run-time, though, if I only
knew how).

In Python, names are bound to objects. The parameter names passed to
a function *are not inherently thread safe*! Python parameters are
not passed-by-value. To show you what I mean:
>spam = ["delicious"]
def test(meal):

... global spam
... if spam is meal:
... print "Spam is the same object as meal"
...>>test(spam)

Spam is the same object as meal

(While the "global spam" statement is optional in this case, I wanted
to make it painfully obvious where the "spam" name in function test is
coming from.)

It is thread-safe to rebind the name "meal" in the function test (ie,
meal = "Green eggs"). It is not thread-safe to mutate or modify the
object that meal is bound to. In the example given above, appending
data to the list, removing data, changing elements, and other
operations will cause potential race conditions across multiple
threads.

Follow Paul's advice and get acquainted with the issues of concurrent
and threaded programming. Judicious locking will help avoid most race
conditions. If you don't want to keep other threads waiting, make a
copy of your data then release the data lock.

Depending on the data, you can usually have multiple threads "reading"
the data, as long as no other threads write to the data while there
are any readers. A writer can be allowed to change the data, but only
if there are no readers and no other writers. (This is commonly known
as a read/write lock.) I didn't see a read/write lock in the Python
documentation with some casual browsing, but one can be implemented
from the existing thread locking mechanisms.

Your description of what you want to do is rather vague, so I can't
get too specific. You've described how you want to do things, but I
don't know what you're trying to accomplish. Where possible, simplify
your design.

--Jason
All I was trying to do, was to get rid of those 'k's in changer():

def change_i(k, arg):
k[0] = arg

def change_j(k, arg):
k[1] = arg

def changer(k):
change_i(k, 'changed_i')
change_j(k, 'changed_j')

def run(i='', j=''):
k = [i, j]
changer(k)
[i, j] = k
return i, j

print run() == ('changed_i', 'changed_j')

Maybe I made a mistake, I should have asked this first, sorry. If the
only way to accomplish this is through locks, then I guess I better
use those 'k's, what do you think?

Thanks Jason, thanks Paul!

Apr 16 '07 #7
I'm reading the docs now and I stumbled upon something:
section "15.3 threading -- Higher-level threading interface" mensions
a class "local", in which "... Thread-local data are data whose values
are thread specific. ..."

Does it mean, I can create global variables whose changing is thread-
safe?
More specific:

import threading

def change_i(arg):
global k
k.i = arg

def change_j(arg):
global k
k.j = arg

def changer():
change_i('changed_i')
change_j('changed_j')

def run(i='', j=''):
global k
k = threading.local()
k.i = i
k.j = j
changer()
i = k.i
j = k.j
return i, j

print run() == ('changed_i', 'changed_j')

Is this ok?

Apr 17 '07 #8
On Apr 17, 3:51 am, ecir.h...@gmail.com wrote:
I'm reading the docs now and I stumbled upon something:
section "15.3 threading -- Higher-level threading interface" mensions
a class "local", in which "... Thread-local data are data whose values
are thread specific. ..."

Does it mean, I can create global variables whose changing is thread-
safe?
More specific:

import threading

def change_i(arg):
global k
k.i = arg

def change_j(arg):
global k
k.j = arg

def changer():
change_i('changed_i')
change_j('changed_j')

def run(i='', j=''):
global k
k = threading.local()
k.i = i
k.j = j
changer()
i = k.i
j = k.j
return i, j

print run() == ('changed_i', 'changed_j')

Is this ok?
I was too quick, "k = threading.local()" has to by outside of run(),
right?

Apr 17 '07 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Peter | last post by:
My client wants to develop a web application using Java. I have several questions and seeking for MVP advise. 1. Does IIS support Sun Micro Java? 2. Is it possible for .NET to mix with Java,...
5
by: Peter | last post by:
My client wants to develop a web application using Java. I have several questions and seeking for MVP advise. 1. Does IIS support Sun Micro Java? 2. Is it possible for .NET to mix with Java,...
1
by: castironpi | last post by:
What if I say oath= yield or other= yield ?
13
by: Martin Sand Christensen | last post by:
Hi! First a bit of context. Yesterday I spent a lot of time debugging the following method in a rather slim database abstraction layer we've developed: ,---- | def selectColumn(self,...
17
by: castironpi | last post by:
Why can't I write this?
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.