PDA

View Full Version : Python Threading question


lme@
November 20th, 2008, 08:37
Not a specific FreeBSD question, but let's see what the people around here know about Python. ;)

I'd like to do some threaded ssh connections with threading.Thread() and system.
To do that I wrote a function1 which connects to one host via ssh and a function2 which loops through a list of hosts and starts a thread with function1 and one host at a time as the function1's argument.
Here is where the fun comes in:
Not the hostname is given as an argument but every single character of it. So I am getting the error message that there are 8 arguments passed on to function1 instead of 1.

You can find the code snippet and the error message here:

http://bsdpaste.bsdgroup.de/1016


Any ideas anyone?

vermaden
November 20th, 2008, 08:53
maybe that:
-DB_HOSTS = ('HOST1234', 'HOST5678')
+DB_HOSTS = ("HOST1234", "HOST5678")

lme@
November 20th, 2008, 09:42
With "" it doesn't work either.
The funny thing is that when I extend check_zip_comp(host) to check_zip_comp(foo, host) and pass args=(foo, hosts) then it works and the host is parsed correctly.

dap
November 20th, 2008, 20:34
Could you post a more complete code that we could test ? Maybe that would help.

lme@
November 20th, 2008, 21:54
Okay, here it is, just c&p and run it:


#!/usr/bin/env python

import os
import sys
from threading import Thread

HOSTS = ('FOOBAR', 'BLAH')

def my_func(host):
print host
return

my_threads = []
for host in HOSTS:
t = Thread(target=my_func, args=host)
my_threads.append(t)
t.start()
for thread in my_threads:
thread.join()

sys.exit(0)


With syntax highlighting: http://bsdpaste.bsdgroup.de/1017

tyson
November 21st, 2008, 01:35
Im not very good in Python, but with little searching in documentation you could make smth liek :

my_threads = []
for host in HOSTS:
t = Thread(target=my_func, args=(host,))
my_threads.append(t)
t.start()


This is because of :

class threading.Thread(group=None, target=None, name=None, args=(), kwargs={})

This constructor should always be called with keyword arguments. Arguments are:

group should be None; reserved for future extension when a ThreadGroup class is implemented.

target is the callable object to be invoked by the run() method. Defaults to None, meaning nothing is called.

name is the thread name. By default, a unique name is constructed of the form “Thread-N” where N is a small decimal number.

args is the argument tuple for the target invocation. Defaults to ().


and the (host,) create one element tuple.

lme@
November 21st, 2008, 09:04
Im not very good in Python, but with little searching in documentation you could make smth liek :

my_threads = []
for host in HOSTS:
t = Thread(target=my_func, args=(host,))
my_threads.append(t)
t.start()


This is because of :


and the (host,) create one element tuple.

Thanks a lot for the explanation! It's working now. Now I even managed to get it working with args=[host].

Python is a little strange. ;)

roddierod
November 26th, 2008, 16:18
Thanks a lot for the explanation! It's working now. Now I even managed to get it working with args=[host].

Python is a little strange. ;)

I believe this is because [] is syntax for a list and a tuple () is an immutable list.

Djn
November 26th, 2008, 17:23
Basically, it expects something subscriptable with a length, and a string qualifies even though that's not quite what you meant.

In python, strings implement __getitem__, __getslice__, __setitem__, __setslice__, __len__ and __iter__, so you can treat them like a list. A side effect is that when you pass a string to something that expects a tuple or list of strings, it acts just like if you passed a list of strings of length 1. Which is why you need to construct a one-element tuple or list with the string in it when passing it to a method like this.

It's perhaps a bit odd, but it makes sense. :)
(It's also an example of duck typing in action: The argument is supposed to be a list; so try using whatever we got as one. If that works, fine.)