Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Python (http://www.velocityreviews.com/forums/f43-python.html)
-   -   multithreading-problem (http://www.velocityreviews.com/forums/t320173-multithreading-problem.html)

Diez B. Roggisch 07-27-2003 04:24 PM

multithreading-problem
 
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

Manish Jethani 07-27-2003 08:14 PM

Re: multithreading-problem
 
Diez B. Roggisch wrote:

> 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

--
Manish Jethani (manish.j at gmx.net)
phone (work) +91-80-51073488


Scott David Daniels 07-27-2003 08:29 PM

Re: multithreading-problem
 
Diez B. Roggisch wrote:
> ...
> 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
Scott.Daniels@Acm.Org


=============================
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


Diez B. Roggisch 07-27-2003 08:29 PM

Re: multithreading-problem
 
Manish Jethani wrote:

>>
>> 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()


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

Diez B. Roggisch 07-27-2003 08:35 PM

Re: multithreading-problem
 
> 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


All times are GMT. The time now is 05:36 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.