Humble Penguin
Humble Penguin

Reputation: 323

How to pass arguments to a python greenlet as additional arguments

I'm looking for a way to pass function arguments through another function, in a manner identical to Stackless' tasklet instantiation:

stackless.tasklet(function_being_called)(*args)

So far the best way I've come up with is:

mylib.tasklet(function_being_called,*args)

which works, but is not identical to Stackless' syntax. I'm not sure where to look in the documentation to find out how to accomplish this (hence the rather ambiguous title for this question). Is this even possible, or is it part of Stackless' changes to the interpreter?

EDIT: I'm now aware that there is an approach which will work for functions, but I'm unsure if it will work in my case. I'm using the greenlet library: greenlet threads obtain args when the greenlet is switch()ed to, not on instantiation. Calling them as shown below results in

TypeError: 'greenlet.greenlet' object is not callable.

Using greenlet.greenlet(function(args)) (still not right syntax) executes immediately and still requires args in the switch() method. Hence I currently store variables in-class, using the syntax shown above, to pass when calling switch(). Hope this doesn't change the question too much!

As requested, here is the code in question. First, a variant on eri's answer (DISCLAIMER: I've never used decorators before):

import greenlet # Background "greenlet" threadlet library

_scheduled = [] # Scheduler queue

def newtasklet(func): # Returns a greenlet-making function & switch() arguments. 
    def inner(*args,**kwargs):
        newgreenlet = greenlet.greenlet(func,None)
        return newgreenlet,args,kwargs
    return inner

class tasklet():
    def __init__(self,function=None):
        global _scheduled 
        initializer = newtasklet(function)
        self.greenlet,self.variables,self.kvars = initializer()
        _scheduled.append(self)
        self.blocked = False

tasklet(print)("A simple test using the print function.")

Traceback (most recent call last):
  File "<pyshell#604>", line 1, in <module>
    tasklet(print)("A simple test using the print function.")
TypeError: 'tasklet' object is not callable

Original code (working but not syntactically ideal):

class tasklet(): 
    def __init__(self,function=None,*variables,parent=None):
        global _scheduled
        self.greenlet = greenlet.greenlet(function,parent)
        self.variables = variables
        _scheduled.append(self)
        self.blocked = False

>>> tasklet(print,"A simple test using the print function.")
<__main__.tasklet object at 0x7f352280e610>
>>> a = _scheduled.pop()
>>> a.greenlet.switch(*a.variables)
A simple test using the print function.

Upvotes: 1

Views: 1830

Answers (5)

Gabe
Gabe

Reputation: 1286

I'm not familiar with Stackless, but what's happening there is that the tasklet functions returns a reference to the function, that is then called by the interpreter with the *args.

An example:

def return_the_method(method):
    return method

def add_two(num1, num2):
    return num1 + num2

If you have this, then run return_the_method(add_two)(1, 2), you'll get 3.

Upvotes: 1

Aderbal
Aderbal

Reputation: 1

import greenlet # Background "greenlet" threadlet library

_scheduled = [] # Scheduler queue

def newtasklet(func): # Returns a greenlet-making function & switch() arguments. def inner(*args,**kwargs): newgreenlet = greenlet.greenlet(func,None) return newgreenlet,args,kwargs return inner

class tasklet(): def init(self,function=None): global _scheduled initializer = newtasklet(function) self.greenlet,self.variables,self.kvars = initializer() _scheduled.append(self) self.blocked = False def call(self, function=None): return function

def imprime(a): print a

tasklet(imprime)("A simple test using the print function.")

Upvotes: 0

user2479509
user2479509

Reputation: 334

Just make sure to return a function from mylib.tasklet:

>>> def call_me(func):
        # do something here, like spawn a thread
        return func

>>> def being_called(str1, str2, str3):
        print str1
        print str2
        print str3

>>> call_me(being_called)('a', 'b', 'c')
a
b
c

Upvotes: 1

eri
eri

Reputation: 3514

stackless.tasklet is decorator. Rewrite your function as decorator.

def tasklet(f):
  def inner(*args,**kwargs):
    t= Thread(target=f,args=args,kwargs=kwargs)
    t.start()
    return t
  return inner


task=tasklet(your_func)(arg)
task.join()

It runs your_func in separate thread and returns thread instance.

Upvotes: 1

mr2ert
mr2ert

Reputation: 5186

I've never used stackless before, but stackless.tasklet(function_being_called) is returning a function object that is being given the parameters (*args). If you want the syntax to be the same for your tasklet, then mylib.tasklet should return a function.

For example:

def inner(*args):
    print '|'.join(args)

def foo(func):
    return func

foo(inner)('hello', 'world')

Outputs:

hello|world

Upvotes: 0

Related Questions