user2565554
user2565554

Reputation: 447

Learning the Python Thread Module

I am trying to learn more about the thread module. I've come up with a quick script but am getting an error when I run it. The docs show the format as:

thread.start_new_thread ( function, args[, kwargs] )

My method only has one argument.

#!/usr/bin/python

import ftplib
import thread

sites = ["ftp.openbsd.org","ftp.ucsb.edu","ubuntu.osuosl.org"]

def ftpconnect(target):
        ftp = ftplib.FTP(target)
        ftp.login()
        print "File list from: %s" % target
        files = ftp.dir()
        print files

for i in sites:
    thread.start_new_thread(ftpconnect(i))

The error I am seeing occurs after one iteration of the for loop:

Traceback (most recent call last): File "./ftpthread.py", line 16, in thread.start_new_thread(ftpconnect(i)) TypeError: start_new_thread expected at least 2 arguments, got 1

Any suggestions for this learning process would be appreciated. I also looked into using threading, but I am unable to import threading since its not install apparently and I haven't found any documentation for installing that module yet.

Thank You!

There error I get when trying to import threading on my Mac is:

>>> import threading
# threading.pyc matches threading.py
import threading # precompiled from threading.pyc
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "threading.py", line 7, in <module>
    class WorkerThread(threading.Thread) :
AttributeError: 'module' object has no attribute 'Thread'

Upvotes: 1

Views: 7850

Answers (3)

Max Noel
Max Noel

Reputation: 8910

The thread.start_new_thread function is really low-level and doesn't give you a lot of control. Take a look at the threading module, more specifically the Thread class: http://docs.python.org/2/library/threading.html#thread-objects

You then want to replace the last 2 lines of your script with:

# This line should be at the top of your file, obviously :p
from threading import Thread 

threads = []
for i in sites:
    t = Thread(target=ftpconnect, args=[i])
    threads.append(t)
    t.start()

# Wait for all the threads to complete before exiting the program.
for t in threads:
    t.join()

Your code was failing, by the way, because in your for loop, you were calling ftpconnect(i), waiting for it to complete, and then trying to use its return value (that is, None) to start a new thread, which obviously doesn't work.

In general, starting a thread is done by giving it a callable object (function/method -- you want the callable object, not the result of a call -- my_function, not my_function()), and optional arguments to give the callable object (in our case, [i] because ftpconnect takes one positional argument and you want it to be i), and then calling the Thread object's start method.

Upvotes: 5

Tim Peters
Tim Peters

Reputation: 70592

Now that you can import threading, start with best practices at once ;-)

import threading
threads = [threading.Thread(target=ftpconnect, args=(s,))
           for s in sites]
for t in threads:
    t.start()
for t in threads:  # shut down cleanly
    t.join()

Upvotes: 3

snapshoe
snapshoe

Reputation: 14264

What you want is to pass the function object and arguments to the function to thread.start_new_thread, not execute the function.

Like this:

for i in sites:
    thread.start_new_thread(ftpconnect, (i,))

Upvotes: 1

Related Questions