Having problems accepting parameters to a function

R

rh0dium

Hi Experts!!

I am trying to get the following little snippet to push my data to the
function func(). What I would expect to happen is it to print out the
contents of a and loglevel. But it's not working. Can someone please
help me out.

---------<snip>--------------
#!/usr/bin/env python

import random

def func(*args, **kwargs):
print kwargs.get('a', "NOPE")
print kwargs.get('loglevel', "NO WAY")

def main():
b = []
for x in range(5):
b.append({'a':random.random(), "loglevel":10})

for y in b:
apply(func,y)

# First attempt - didn't work
# for y in b:
# func(y)

if __name__ == '__main__':
main()
 
S

Stargaming

rh0dium said:
Hi Experts!!

I am trying to get the following little snippet to push my data to the
function func(). What I would expect to happen is it to print out the
contents of a and loglevel. But it's not working. Can someone please
help me out.

---------<snip>--------------
#!/usr/bin/env python

import random

def func(*args, **kwargs):
print kwargs.get('a', "NOPE")
print kwargs.get('loglevel', "NO WAY")

def main():
b = []
for x in range(5):
b.append({'a':random.random(), "loglevel":10})

for y in b:
apply(func,y)

# First attempt - didn't work
# for y in b:
# func(y)

if __name__ == '__main__':
main()
``apply()`` is deprecated -- use the asterisk-syntax_ instead.
.... print kwargs
....{'a': 5, 'loglevel': 10}

So, your first attempt was close -- just two signs missing. :)

HTH,
Stargaming

... _asterisk-sytax:
http://docs.python.org/tut/node6.html#SECTION006740000000000000000
 
7

7stud

Hi Experts!!

I am trying to get the following little snippet to push my data to the
function func(). What I would expect to happen is it to print out the
contents of a and loglevel. But it's not working. Can someone please
help me out.

---------<snip>--------------
#!/usr/bin/env python

import random

def func(*args, **kwargs):
print kwargs.get('a', "NOPE")
print kwargs.get('loglevel', "NO WAY")

def main():
b = []
for x in range(5):
b.append({'a':random.random(), "loglevel":10})

for y in b:
apply(func,y)

# First attempt - didn't work
# for y in b:
# func(y)

if __name__ == '__main__':
main()

1) apply() is deprecated

2) You need to unpack the dictionary using ** before sending it to
func(), whereupon it will be repacked into a dictionary.


import random

def func(*args, **kwargs):
print kwargs.get('a', "NOPE")
print kwargs.get('loglevel', "NO WAY")

def main():
b = []
for x in range(5):
b.append({'a':random.random(), "loglevel":10})

for y in b:
func(**y)

if __name__ == '__main__':
main()


You might consider redefining func() so that you don't have to do the
unpack--repack:
 
7

7stud

You might consider redefining func() so that you don't have to do the
unpack--repack...

When you define a function like this:

def func(**keywordargs):
print keywordargs

the function expects to receive arguments in the form:

func(a="hello", b="world")

not:

func(adict)
 
R

rh0dium

Thanks to all who helped!!

Let me expand a bit more - I am working on a threading class and I
want to be able to push on the Queue a list of args. If you run the
following program - I am failing to understand how to push items onto
the queue in a manner so that func2 recognizes them as kwargs not as
args. Can anyone help me with this.

test1 works
test2 fails again I can't figure out how to push onto the queue a
dictionary and get it back off.

I know this is a lot longer than I tend to post but I really want to
solve this bugger.


Any help is greatly appreciated.

------------<snip>----------------

#!/usr/bin/env python
# encoding: utf-8
"""
myThreading.py
"""

import sys
import os
import traceback
import logging
import threading
import Queue

LOGLEVEL=logging.DEBUG

# Basic logger
logging.basicConfig(level=LOGLEVEL, format="%(asctime)s %(name)s %
(levelname)-8s %(message)s",
datefmt='%d %b %Y %H:%M:%S', stream=sys.stderr)

# Identifies (hopefully) the current module name
try:
module= os.path.basename(traceback.extract_stack(limit=2)[1]
[0]).split(".py")[0]+"."
except:
module = os.path.basename(traceback.extract_stack(limit=2)[0]
[0]).split(".py")[0]+"."

class myThread(threading.Thread):

def __init__(self, *args, **kwargs):
"""description"""

self.id = kwargs.get('id', 0)
self.requestQ = kwargs.get('requestQ', None)
self.responseQ = kwargs.get('responseQ', None)
self.function = kwargs.get('function', None)

# Setup Logging
self.log = logging.getLogger(module+self.__class__.__name__
+"."+str(self.id))
self.loglevel = kwargs.get('loglevel', logging.WARN)
self.setLoglevel(self.loglevel)

self.log.debug("Starting Thread %d" % self.id)
threading.Thread.__init__(self, name=module
+self.__class__.__name__+"."+str(self.id))

def setLoglevel(self,loglevel):
"""setLog log level"""
if loglevel is not False:
self.log.setLevel(loglevel)
self.log.debug("Setting Logging level to %s" % loglevel)
else:
self.log.setLevel(logging.WARN)

if self.loglevel == logging.DEBUG: self.debug = True
else: self.debug=False

def run(self):
while 1:
input = self.requestQ.get()
if input is None:
self.log.debug("Ending the thread - Recieved None")
if self.responseQ is not None:
self.responseQ.put(None)
break
self.log.info("Applying %s to function %s" %
(str(input),str(self.function.__name__)))
result = self.function(input)
if self.responseQ is not None:
self.log.debug("Response recieved = %s" % result)
self.responseQ.put(result)

def func(input):
import time
time.sleep(input)
return 2*input

def test1(loglevel=False):

log = logging.getLogger(module+sys._getframe().f_code.co_name )
if loglevel is not False: log.setLevel(loglevel)
else:log.setLevel(logging.WARN)

maxThreads=5

# Set up two queues one for sending request data (req) one for
getting response to the request (res)
reqQ = Queue.Queue()
resQ = Queue.Queue()

# Push some data onto the reqestQ end it with None
import random
for x in range(200): reqQ.put(random.random())
for n in range(maxThreads): reqQ.put(None)

# Start Up some threads to do some work
for n in range(maxThreads):
t = myThread(id=n,loglevel=logging.INFO, function=func,
requestQ=reqQ, responseQ=resQ).start()

# Collect the results
results = 0
while 1:
try:
data = resQ.get()
if data is None:
break
else:
results += data
except:
break
print results

def func2( input, loglevel=False ):

import time

#print "args", args
#print "kwargs", kwargs

log = logging.getLogger(module+sys._getframe().f_code.co_name )
#loglevel = kwargs.get('loglevel', logging.WARN)
log.setLevel(loglevel)

# input = kwargs.get('input', 0.0)
log.debug("Using input %s" % str(input))
time.sleep(input)
return 3*input

def test2(loglevel=False):

log = logging.getLogger(module+sys._getframe().f_code.co_name )
if loglevel is not False: log.setLevel(loglevel)
else:log.setLevel(logging.WARN)

maxThreads=5

# Set up two queues one for sending request data (req) one for
getting response to the request (res)
reqQ = Queue.Queue()
resQ = Queue.Queue()

# Push some data onto the reqestQ end it with None
import random
for x in range(5): reqQ.put({'input':random.random(),
'loglevel':loglevel})
for n in range(maxThreads): reqQ.put(None)

# Start Up some threads to do some work
for n in range(maxThreads):
t = myThread(id=n,loglevel=logging.INFO, function=func2,
requestQ=reqQ, responseQ=resQ).start()

# Collect the results
results = 0
while 1:
try:
data = resQ.get()
if data is None:
break
else:
results += data
except:
break
print results

def main(loglevel=False):
""" """
# Setup Logging
log = logging.getLogger(module+sys._getframe().f_code.co_name )
if loglevel is not False: log.setLevel(loglevel)
else:log.setLevel(logging.WARN)

# test1(loglevel)
test2(loglevel)


if __name__ == '__main__':
sys.exit(main(loglevel=LOGLEVEL))
 
7

7stud

kwargs is not a built in name--it's a made up name used in the
docs. Would you expect this function to work:

def somefunc(x=10, y=20):
print a

The best way to figure out a feature of a programming language that
you don't understand is not in the middle of some complex program.
Instead, you should begin a new program, or if you are smart you will
already have several blank programs already created waiting in the
wings for testing purposes. In the new program, you can play around
with functions, default values and catch all parameters like *a and
**b to figure out how they work.
 
G

Gabriel Genellina

Let me expand a bit more - I am working on a threading class and I
want to be able to push on the Queue a list of args. If you run the
following program - I am failing to understand how to push items onto
the queue in a manner so that func2 recognizes them as kwargs not as
args. Can anyone help me with this.

You can put a tuple in the queue: the first item being the positional
arguments, the second item being a dictionary used as keyword arguments.

py> from Queue import Queue
py> q = Queue()
py> q.put(((1,2,3),{"a":100, "b":200}))
py> q.put(((),dict(boca=2,racing=2)))
py> def f(*args, **kw):
.... print "args", args
.... for k in kw:
.... print k, kw[k]
....
py> item = q.get()
py> f(*item[0], **item[1])
args (1, 2, 3)
a 100
b 200
py> args, kw = q.get()
py> f(*args, **kw)
args ()
racing 2
boca 2
 

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

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,737
Latest member
Georgeengab

Latest Threads

Top