multithreading-problem

D

Diez B. Roggisch

Hi,

I expirienced strange problems when using the module threading:

class Bar:
def __init__(_, arg):
_.arg = arg
def work(_):
while 1:
print _.arg

def foo(arg):
b = Bar(arg)
b.work()

for i in xrange(4):
thread = threading.Thread(target=lambda : foo(i))
thread.start()

What I'd expect would be a sequence of prints like this
1
2
3
4
1
3
4
2

What I actualy get is this:
1
4
4
4
4
1
4
4
4

Placing a time.sleep(3) after the thread.start() fixed things. So it appears
that the curried lambda passed as target is somehow a reference equal for
all four invocations.

The used python is 2.2.<latest-cygwin>.

Regards,

Diez
 
M

Manish Jethani

Diez said:
Hi,

I expirienced strange problems when using the module threading:

class Bar:
def __init__(_, arg):
_.arg = arg
def work(_):
while 1:
print _.arg

def foo(arg):
b = Bar(arg)
b.work()

for i in xrange(4):
thread = threading.Thread(target=lambda : foo(i))
thread.start()

What I'd expect would be a sequence of prints like this
1
2
3
4
1
3
4
2

What I actualy get is this:
1
4
4
4
4
1
4
4
4

Placing a time.sleep(3) after the thread.start() fixed things. So it appears
that the curried lambda passed as target is somehow a reference equal for
all four invocations.

No, I don't believe it to be true. It's probably just that the
other threads aren't getting a chance to run. Consider
time.sleep(0) in the while loop in work()

-Manish
 
S

Scott David Daniels

Diez said:
...
for i in xrange(4):
thread = threading.Thread(target=lambda : foo(i))
thread.start()
... So it appears that the curried lambda passed as target is
> somehow a reference equal for all four invocations....
This is why the "curry" recipe dances more jig than you have.
the lambda-expression that you've passed in did not do any
value-capture. The smallest fix is:
> ...
> for i in xrange(4):
> thread = threading.Thread(target=lambda v=i: foo(v))
> thread.start()
> ...

With curry from the Python Cookbook (or as below), I'd write:
> ...
> for i in xrange(4):
> thread = threading.Thread(target=curry(foo, i))
> thread.start()
> ...

The problem is that your lambda expression looks up "i" at function
evaluation time (when target is called), not when you assign the
target function for the thread.

-Scott David Daniels
(e-mail address removed)


=============================
for 2.2 I define curry as:

from __future__ import nested_scopes

def curry(*_args, **_kwargs):
"""curry(f,<args>)(<more>) == f(<args>, <more>) (roughly).

keyword args in the curry call can be overridden by keyword args
in the later call; curry can be used to change defaults.
"""
def result(*__args, **__kwargs):
if _kwargs and __kwargs:
kwargs = _kwargs.copy()
kwargs.update(__kwargs)
else:
kwargs = _kwargs or __kwargs
return _args[0](*(_args[1:]+__args), **kwargs)
return result
 
D

Diez B. Roggisch

Manish said:
No, I don't believe it to be true. It's probably just that the
other threads aren't getting a chance to run. Consider
time.sleep(0) in the while loop in work()

No, they all run - just a few of them have the same parameters. In my real
app, all of them do some work, which takes an individual amount of time. In
the main-thread I wait for all of them to be terminated, and while doing
that print how much are still running. All this works as expected. The only
thing not working is the parameter passing.

Diez
 
D

Diez B. Roggisch

The problem is that your lambda expression looks up "i" at function
evaluation time (when target is called), not when you assign the
target function for the thread.

Ah, ok. That makes sense. Where do I find this curry-function, only in the
book? It appears not to be a standard function.

Regards, Diez
 

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,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top